1 /**********************************************************************
2  * $Id: mitab.h fa752ad6eabafaf630a704e1892a9d837d683cb3 2021-03-06 17:04:38 +0100 Even Rouault $
3  *
4  * Name:     mitab.h
5  * Project:  MapInfo TAB Read/Write library
6  * Language: C++
7  * Purpose:  Header file containing public definitions for the library.
8  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
9  *
10  **********************************************************************
11  * Copyright (c) 1999-2005, Daniel Morissette
12  * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included
22  * in all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
27  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  * DEALINGS IN THE SOFTWARE.
31  **********************************************************************/
32 
33 #ifndef MITAB_H_INCLUDED_
34 #define MITAB_H_INCLUDED_
35 
36 #include "mitab_priv.h"
37 #include "ogr_feature.h"
38 #include "ogr_featurestyle.h"
39 #include "ogrsf_frmts.h"
40 
41 #include <set>
42 
43 /*---------------------------------------------------------------------
44  * Current version of the MITAB library... always useful!
45  *--------------------------------------------------------------------*/
46 #define MITAB_VERSION      "2.0.0-dev (2008-10)"
47 #define MITAB_VERSION_INT  2000000  /* version x.y.z -> xxxyyyzzz */
48 
49 #ifndef ROUND_INT
50 #  define ROUND_INT(dX) static_cast<int>((dX) < 0.0 ? (dX)-0.5 : (dX)+0.5 )
51 #endif
52 
53 #define MITAB_AREA(x1, y1, x2, y2)  ((static_cast<double>(x2)-(x1))*(static_cast<double>(y2)-(y1)))
54 
55 class TABFeature;
56 
57 /*---------------------------------------------------------------------
58  * Codes for the GetFileClass() in the IMapInfoFile-derived  classes
59  *--------------------------------------------------------------------*/
60 typedef enum
61 {
62     TABFC_IMapInfoFile = 0,
63     TABFC_TABFile,
64     TABFC_TABView,
65     TABFC_TABSeamless,
66     TABFC_MIFFile
67 } TABFileClass;
68 
69 /*---------------------------------------------------------------------
70  *                      class IMapInfoFile
71  *
72  * Virtual base class for the TABFile and MIFFile classes.
73  *
74  * This is the definition of the public interface methods that should
75  * be available for any type of MapInfo dataset.
76  *--------------------------------------------------------------------*/
77 
78 class IMapInfoFile CPL_NON_FINAL: public OGRLayer
79 {
80     CPL_DISALLOW_COPY_ASSIGN(IMapInfoFile)
81 
82   protected:
83     GIntBig             m_nCurFeatureId;
84     TABFeature         *m_poCurFeature;
85     GBool               m_bBoundsSet;
86 
87     char                *m_pszCharset;
88     std::set<CPLString> m_oSetFields{};
89     TABFeature*         CreateTABFeature(OGRFeature *poFeature);
90 
91   public:
92     IMapInfoFile() ;
93     virtual ~IMapInfoFile();
94 
95     virtual TABFileClass GetFileClass() {return TABFC_IMapInfoFile;}
96 
97     virtual int Open(const char *pszFname, const char* pszAccess,
98                      GBool bTestOpenNoError = FALSE,
99                      const char* pszCharset = nullptr );
100 
101     virtual int Open(const char *pszFname, TABAccess eAccess,
102                      GBool bTestOpenNoError = FALSE,
103                      const char* pszCharset = nullptr ) = 0;
104     virtual int Close() = 0;
105 
106     virtual int SetQuickSpatialIndexMode(CPL_UNUSED GBool bQuickSpatialIndexMode=TRUE) {return -1;}
107 
108     virtual const char *GetTableName() = 0;
109 
110     ///////////////
111     // Static method to detect file type, create an object to read that
112     // file and open it.
113     static IMapInfoFile *SmartOpen(const char *pszFname,
114                                    GBool bUpdate = FALSE,
115                                    GBool bTestOpenNoError = FALSE);
116 
117     ///////////////
118     //  OGR methods for read support
119     virtual void        ResetReading() override = 0;
120     virtual GIntBig     GetFeatureCount (int bForce) override = 0;
121     virtual OGRFeature *GetNextFeature() override;
122     virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
123     virtual OGRErr      ICreateFeature(OGRFeature *poFeature) override;
124     virtual int         TestCapability( const char * pszCap ) override =0;
125     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override =0;
126     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
127                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
128 
129     ///////////////
130     // Read access specific stuff
131     //
132     virtual GIntBig GetNextFeatureId(GIntBig nPrevId) = 0;
133     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) = 0;
134     virtual OGRFeatureDefn *GetLayerDefn() override = 0;
135 
136     virtual TABFieldType GetNativeFieldType(int nFieldId) = 0;
137 
138     virtual int GetBounds(double &dXMin, double &dYMin,
139                           double &dXMax, double &dYMax,
140                           GBool bForce = TRUE ) = 0;
141 
142     virtual OGRSpatialReference *GetSpatialRef() override = 0;
143 
144     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
145                                       int &numRegions, int &numTexts,
146                                       GBool bForce = TRUE ) = 0;
147 
148     virtual GBool IsFieldIndexed(int nFieldId) = 0;
149     virtual GBool IsFieldUnique(int nFieldId) = 0;
150 
151     ///////////////
152     // Write access specific stuff
153     //
154     GBool       IsBoundsSet()            {return m_bBoundsSet;}
155     virtual int SetBounds(double dXMin, double dYMin,
156                           double dXMax, double dYMax) = 0;
157     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
158                             TABFieldType *paeMapInfoNativeFieldTypes = nullptr)=0;
159     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
160                                int nWidth=0, int nPrecision=0,
161                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
162                                int bApproxOK = TRUE) = 0;
163     virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) override;
164 
165     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) = 0;
166 
167     virtual OGRErr CreateFeature(TABFeature *poFeature) = 0;
168 
169     virtual int SetFieldIndexed(int nFieldId) = 0;
170 
171     virtual int SetCharset(const char* charset);
172 
173     virtual const char* GetCharset() const;
174 
175     static const char* CharsetToEncoding( const char* );
176     static const char* EncodingToCharset( const char* );
177 
178     void SetEncoding( const char* );
179     const char* GetEncoding() const;
180     int TestUtf8Capability() const;
181     CPLString NormalizeFieldName(const char *pszName) const;
182     ///////////////
183     // semi-private.
184     virtual int  GetProjInfo(TABProjInfo *poPI) = 0;
185     virtual int  SetProjInfo(TABProjInfo *poPI) = 0;
186     virtual int  SetMIFCoordSys(const char *pszMIFCoordSys) = 0;
187 
188     static int GetTABType( OGRFieldDefn *poField, TABFieldType* peTABType,
189                            int *pnWidth, int *pnPrecision);
190 
191 #ifdef DEBUG
192     virtual void Dump(FILE *fpOut = nullptr) = 0;
193 #endif
194 };
195 
196 /*---------------------------------------------------------------------
197  *                      class TABFile
198  *
199  * The main class for TAB datasets.  External programs should use this
200  * class to open a TAB dataset and read/write features from/to it.
201  *
202  *--------------------------------------------------------------------*/
203 class TABFile final : public IMapInfoFile
204 {
205     CPL_DISALLOW_COPY_ASSIGN(TABFile)
206 
207   private:
208     char        *m_pszFname;
209     TABAccess   m_eAccessMode;
210     char        **m_papszTABFile;
211     int         m_nVersion;
212     int         *m_panIndexNo;
213     TABTableType m_eTableType;  // NATIVE (.DAT) or DBF
214 
215     TABDATFile  *m_poDATFile;   // Attributes file
216     TABMAPFile  *m_poMAPFile;   // Object Geometry file
217     TABINDFile  *m_poINDFile;   // Attributes index file
218 
219     OGRFeatureDefn *m_poDefn;
220     OGRSpatialReference *m_poSpatialRef;
221     int         bUseSpatialTraversal;
222 
223     int         m_nLastFeatureId;
224 
225     GIntBig    *m_panMatchingFIDs;
226     int         m_iMatchingFID;
227 
228     int         m_bNeedTABRewrite;
229 
230     int         m_bLastOpWasRead;
231     int         m_bLastOpWasWrite;
232     ///////////////
233     // Private Read access specific stuff
234     //
235     int         ParseTABFileFirstPass(GBool bTestOpenNoError);
236     int         ParseTABFileFields();
237 
238      ///////////////
239     // Private Write access specific stuff
240     //
241     int         WriteTABFile();
242 
243   public:
244     TABFile();
245     virtual ~TABFile();
246 
247     virtual TABFileClass GetFileClass() override {return TABFC_TABFile;}
248 
249     virtual int Open(const char *pszFname, const char* pszAccess,
250                      GBool bTestOpenNoError = FALSE,
251                      const char* pszCharset = nullptr ) override
252             { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError, pszCharset); }
253     virtual int Open(const char *pszFname, TABAccess eAccess,
254                      GBool bTestOpenNoError = FALSE,
255                      const char* pszCharset = nullptr ) override
256             { return Open(pszFname, eAccess, bTestOpenNoError, 512, pszCharset); }
257 
258     virtual int Open(const char *pszFname, TABAccess eAccess,
259                      GBool bTestOpenNoError,
260                      int nBlockSizeForCreate,
261                      const char* pszCharset );
262 
263     virtual int Close() override;
264 
265     virtual int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode=TRUE) override;
266 
267     virtual const char *GetTableName() override
268                             {return m_poDefn?m_poDefn->GetName():"";}
269 
270     virtual void        ResetReading() override;
271     virtual int         TestCapability( const char * pszCap ) override;
272     virtual GIntBig     GetFeatureCount (int bForce) override;
273     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
274     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
275                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
276 
277     /* Implement OGRLayer's SetFeature() for random write, only with TABFile */
278     virtual OGRErr      ISetFeature( OGRFeature * ) override;
279     virtual OGRErr      DeleteFeature(GIntBig nFeatureId) override;
280 
281     virtual OGRErr      DeleteField( int iField ) override;
282     virtual OGRErr      ReorderFields( int* panMap ) override;
283     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
284 
285     virtual OGRErr      SyncToDisk() override;
286 
287     virtual CPLErr SetMetadataItem( const char * pszName,
288                                     const char * pszValue,
289                                     const char * pszDomain = "" ) override;
290 
291     ///////////////
292     // Read access specific stuff
293     //
294 
295     int         GetNextFeatureId_Spatial( int nPrevId );
296 
297     virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
298     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
299     virtual OGRFeatureDefn *GetLayerDefn() override;
300 
301     virtual TABFieldType GetNativeFieldType(int nFieldId) override;
302 
303     virtual int GetBounds(double &dXMin, double &dYMin,
304                           double &dXMax, double &dYMax,
305                           GBool bForce = TRUE ) override;
306 
307     virtual OGRSpatialReference *GetSpatialRef() override;
308 
309     static OGRSpatialReference* GetSpatialRefFromTABProj(const TABProjInfo& sTABProj);
310     static int                  GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
311                                                          TABProjInfo& sTABProj, int& nParamCount);
312 
313     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
314                                       int &numRegions, int &numTexts,
315                                       GBool bForce = TRUE) override;
316 
317     virtual GBool IsFieldIndexed(int nFieldId) override;
318     virtual GBool IsFieldUnique(int /*nFieldId*/) override   {return FALSE;}
319 
320     virtual int GetVersion() { return m_nVersion; }
321 
322     ///////////////
323     // Write access specific stuff
324     //
325     virtual int SetBounds(double dXMin, double dYMin,
326                           double dXMax, double dYMax) override;
327     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
328                             TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override;
329     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
330                                int nWidth=0, int nPrecision=0,
331                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
332                                int bApproxOK = TRUE) override;
333     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
334 
335     virtual OGRErr CreateFeature(TABFeature *poFeature) override;
336 
337     virtual int SetFieldIndexed(int nFieldId) override;
338 
339     ///////////////
340     // semi-private.
341     virtual int  GetProjInfo(TABProjInfo *poPI) override
342             { return m_poMAPFile->GetHeaderBlock()->GetProjInfo( poPI ); }
343     virtual int  SetProjInfo(TABProjInfo *poPI) override;
344     virtual int  SetMIFCoordSys(const char *pszMIFCoordSys) override;
345 
346     int         GetFieldIndexNumber(int nFieldId);
347     TABINDFile  *GetINDFileRef();
348 
349     TABMAPFile  *GetMAPFileRef() { return m_poMAPFile; }
350 
351     int         WriteFeature(TABFeature *poFeature);
352     virtual int SetCharset(const char* pszCharset) override;
353 #ifdef DEBUG
354     virtual void Dump(FILE *fpOut = nullptr) override;
355 #endif
356 };
357 
358 /*---------------------------------------------------------------------
359  *                      class TABView
360  *
361  * TABView is used to handle special type of .TAB files that are
362  * composed of a number of .TAB datasets linked through some indexed
363  * fields.
364  *
365  * NOTE: The current implementation supports only TABViews composed
366  *       of 2 TABFiles linked through an indexed field of integer type.
367  *       It is unclear if any other type of views could exist anyways.
368  *--------------------------------------------------------------------*/
369 class TABView final : public IMapInfoFile
370 {
371     CPL_DISALLOW_COPY_ASSIGN(TABView)
372 
373   private:
374     char        *m_pszFname;
375     TABAccess   m_eAccessMode;
376     char        **m_papszTABFile;
377     char        *m_pszVersion;
378 
379     char        **m_papszTABFnames;
380     TABFile     **m_papoTABFiles;
381     int         m_numTABFiles;
382     int         m_nMainTableIndex; // The main table is the one that also
383                                    // contains the geometries
384     char        **m_papszFieldNames;
385     char        **m_papszWhereClause;
386 
387     TABRelation *m_poRelation;
388     GBool       m_bRelFieldsCreated;
389 
390     ///////////////
391     // Private Read access specific stuff
392     //
393     int         ParseTABFile(const char *pszDatasetPath,
394                              GBool bTestOpenNoError = FALSE);
395 
396     int         OpenForRead(const char *pszFname,
397                             GBool bTestOpenNoError = FALSE );
398 
399     ///////////////
400     // Private Write access specific stuff
401     //
402     int         OpenForWrite(const char *pszFname );
403     int         WriteTABFile();
404 
405   public:
406     TABView();
407     virtual ~TABView();
408 
409     virtual TABFileClass GetFileClass() override {return TABFC_TABView;}
410 
411     virtual int Open(const char *pszFname, const char* pszAccess,
412                      GBool bTestOpenNoError = FALSE,
413                      const char* pszCharset = nullptr ) override { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError, pszCharset); }
414     virtual int Open(const char *pszFname, TABAccess eAccess,
415                      GBool bTestOpenNoError = FALSE,
416                      const char* pszCharset = nullptr ) override;
417     virtual int Close() override;
418 
419     virtual int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode=TRUE) override;
420 
421     virtual const char *GetTableName() override
422            {return m_poRelation?m_poRelation->GetFeatureDefn()->GetName():"";}
423 
424     virtual void        ResetReading() override;
425     virtual int         TestCapability( const char * pszCap ) override;
426     virtual GIntBig     GetFeatureCount (int bForce) override;
427     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
428     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
429                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
430 
431     ///////////////
432     // Read access specific stuff
433     //
434 
435     virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
436     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
437     virtual OGRFeatureDefn *GetLayerDefn() override;
438 
439     virtual TABFieldType GetNativeFieldType(int nFieldId) override;
440 
441     virtual int GetBounds(double &dXMin, double &dYMin,
442                           double &dXMax, double &dYMax,
443                           GBool bForce = TRUE ) override;
444 
445     virtual OGRSpatialReference *GetSpatialRef() override;
446 
447     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
448                                       int &numRegions, int &numTexts,
449                                       GBool bForce = TRUE) override;
450 
451     virtual GBool IsFieldIndexed(int nFieldId) override;
452     virtual GBool IsFieldUnique(int nFieldId) override;
453 
454     ///////////////
455     // Write access specific stuff
456     //
457     virtual int SetBounds(double dXMin, double dYMin,
458                           double dXMax, double dYMax) override;
459     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
460                            TABFieldType *paeMapInfoNativeFieldTypes=nullptr) override;
461     virtual int AddFieldNative(const char *pszName,
462                                TABFieldType eMapInfoType,
463                                int nWidth=0, int nPrecision=0,
464                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
465                                int bApproxOK = TRUE) override;
466     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
467 
468     virtual OGRErr CreateFeature(TABFeature *poFeature) override;
469 
470     virtual int SetFieldIndexed(int nFieldId) override;
471 
472     ///////////////
473     // semi-private.
474     virtual int  GetProjInfo(TABProjInfo *poPI) override
475             { return m_nMainTableIndex!=-1?
476                      m_papoTABFiles[m_nMainTableIndex]->GetProjInfo(poPI):-1; }
477     virtual int  SetProjInfo(TABProjInfo *poPI) override
478             { return m_nMainTableIndex!=-1?
479                      m_papoTABFiles[m_nMainTableIndex]->SetProjInfo(poPI):-1; }
480     virtual int  SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override {return -1;}
481     virtual int SetCharset(const char* pszCharset) override;
482 
483 #ifdef DEBUG
484     virtual void Dump(FILE *fpOut = nullptr) override;
485 #endif
486 };
487 
488 /*---------------------------------------------------------------------
489  *                      class TABSeamless
490  *
491  * TABSeamless is used to handle seamless .TAB files that are
492  * composed of a main .TAB file in which each feature is the MBR of
493  * a base table.
494  *
495  * TABSeamless are supported for read access only.
496  *--------------------------------------------------------------------*/
497 class TABSeamless final : public IMapInfoFile
498 {
499     CPL_DISALLOW_COPY_ASSIGN(TABSeamless)
500 
501   private:
502     char        *m_pszFname;
503     char        *m_pszPath;
504     TABAccess   m_eAccessMode;
505     OGRFeatureDefn *m_poFeatureDefnRef;
506 
507     TABFile     *m_poIndexTable;
508     int         m_nTableNameField;
509     int         m_nCurBaseTableId;
510     TABFile     *m_poCurBaseTable;
511     GBool       m_bEOF;
512 
513     ///////////////
514     // Private Read access specific stuff
515     //
516     int         OpenForRead(const char *pszFname,
517                             GBool bTestOpenNoError = FALSE );
518     int         OpenBaseTable(TABFeature *poIndexFeature,
519                               GBool bTestOpenNoError = FALSE);
520     int         OpenBaseTable(int nTableId, GBool bTestOpenNoError = FALSE);
521     int         OpenNextBaseTable(GBool bTestOpenNoError =FALSE);
522     static GIntBig     EncodeFeatureId(int nTableId, int nBaseFeatureId);
523     static int         ExtractBaseTableId(GIntBig nEncodedFeatureId);
524     static int         ExtractBaseFeatureId(GIntBig nEncodedFeatureId);
525 
526   public:
527     TABSeamless();
528     virtual ~TABSeamless();
529 
530     virtual TABFileClass GetFileClass() override {return TABFC_TABSeamless;}
531 
532     virtual int Open(const char *pszFname, const char* pszAccess,
533                      GBool bTestOpenNoError = FALSE,
534                      const char* pszCharset = nullptr ) override { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError, pszCharset); }
535     virtual int Open(const char *pszFname, TABAccess eAccess,
536                      GBool bTestOpenNoError = FALSE,
537                      const char* pszCharset = nullptr ) override;
538     virtual int Close() override;
539 
540     virtual const char *GetTableName() override
541            {return m_poFeatureDefnRef?m_poFeatureDefnRef->GetName():"";}
542 
543     virtual void        SetSpatialFilter( OGRGeometry * ) override;
544     virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
545                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
546 
547     virtual void        ResetReading() override;
548     virtual int         TestCapability( const char * pszCap ) override;
549     virtual GIntBig     GetFeatureCount (int bForce) override;
550     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
551     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
552                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
553 
554     ///////////////
555     // Read access specific stuff
556     //
557 
558     virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
559     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
560     virtual OGRFeatureDefn *GetLayerDefn() override;
561 
562     virtual TABFieldType GetNativeFieldType(int nFieldId) override;
563 
564     virtual int GetBounds(double &dXMin, double &dYMin,
565                           double &dXMax, double &dYMax,
566                           GBool bForce = TRUE ) override;
567 
568     virtual OGRSpatialReference *GetSpatialRef() override;
569 
570     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
571                                       int &numRegions, int &numTexts,
572                                       GBool bForce = TRUE) override;
573 
574     virtual GBool IsFieldIndexed(int nFieldId) override;
575     virtual GBool IsFieldUnique(int nFieldId) override;
576 
577     ///////////////
578     // Write access specific stuff
579     //
580     virtual int SetBounds(CPL_UNUSED double dXMin, CPL_UNUSED double dYMin,
581                           CPL_UNUSED double dXMax, CPL_UNUSED double dYMax) override   {return -1;}
582     virtual int SetFeatureDefn(CPL_UNUSED OGRFeatureDefn *poFeatureDefn,
583                                CPL_UNUSED TABFieldType *paeMapInfoNativeFieldTypes=nullptr) override
584                                                         {return -1;}
585     virtual int AddFieldNative(CPL_UNUSED const char *pszName,
586                                CPL_UNUSED TABFieldType eMapInfoType,
587                                CPL_UNUSED int nWidth=0,
588                                CPL_UNUSED int nPrecision=0,
589                                CPL_UNUSED GBool bIndexed=FALSE,
590                                CPL_UNUSED GBool bUnique=FALSE,
591                                CPL_UNUSED int bApproxOK = TRUE) override {return -1;}
592 
593     virtual int SetSpatialRef(CPL_UNUSED OGRSpatialReference *poSpatialRef) override {return -1;}
594 
595     virtual OGRErr CreateFeature(CPL_UNUSED TABFeature *poFeature) override
596                                         {return OGRERR_UNSUPPORTED_OPERATION;}
597 
598     virtual int SetFieldIndexed(CPL_UNUSED int nFieldId) override {return -1;}
599 
600     ///////////////
601     // semi-private.
602     virtual int  GetProjInfo(TABProjInfo *poPI) override
603             { return m_poIndexTable?m_poIndexTable->GetProjInfo(poPI):-1; }
604     virtual int SetProjInfo(CPL_UNUSED TABProjInfo *poPI) override         { return -1; }
605     virtual int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override {return -1;}
606 
607 #ifdef DEBUG
608     virtual void Dump(FILE *fpOut = nullptr) override;
609 #endif
610 };
611 
612 /*---------------------------------------------------------------------
613  *                      class MIFFile
614  *
615  * The main class for (MID/MIF) datasets.  External programs should use this
616  * class to open a (MID/MIF) dataset and read/write features from/to it.
617  *
618  *--------------------------------------------------------------------*/
619 class MIFFile final : public IMapInfoFile
620 {
621     CPL_DISALLOW_COPY_ASSIGN(MIFFile)
622 
623   private:
624     char        *m_pszFname;
625     TABAccess    m_eAccessMode;
626     int          m_nVersion;   /* Dataset version: 300, 450, 600, 900, etc. */
627     char        *m_pszDelimiter;
628     char        *m_pszUnique;
629     char        *m_pszIndex;
630     char        *m_pszCoordSys;
631 
632     TABFieldType *m_paeFieldType;
633     GBool       *m_pabFieldIndexed;
634     GBool       *m_pabFieldUnique;
635 
636     double       m_dfXMultiplier;
637     double       m_dfYMultiplier;
638     double       m_dfXDisplacement;
639     double       m_dfYDisplacement;
640 
641     /* these are the projection bounds, possibly much broader than extents */
642     double      m_dXMin;
643     double      m_dYMin;
644     double      m_dXMax;
645     double      m_dYMax;
646 
647     /* extents, as cached by MIFFile::PreParseFile() */
648     int         m_bExtentsSet;
649     OGREnvelope m_sExtents{};
650 
651     int         m_nPoints;
652     int         m_nLines;
653     int         m_nRegions;
654     int         m_nTexts;
655 
656     int         m_nPreloadedId;  // preloaded mif line is for this feature id
657     MIDDATAFile  *m_poMIDFile;   // Mid file
658     MIDDATAFile  *m_poMIFFile;   // Mif File
659 
660     OGRFeatureDefn *m_poDefn;
661     OGRSpatialReference *m_poSpatialRef;
662 
663     int         m_nFeatureCount;
664     int         m_nWriteFeatureId;
665     int         m_nAttribute;
666 
667     ///////////////
668     // Private Read access specific stuff
669     //
670     int         ReadFeatureDefn();
671     int         ParseMIFHeader(int* pbIsEmpty);
672     void        PreParseFile();
673     int         AddFields(const char *pszLine);
674     int         GotoFeature(int nFeatureId);
675     int         NextFeature();
676 
677     ///////////////
678     // Private Write access specific stuff
679     //
680     GBool       m_bPreParsed;
681     GBool       m_bHeaderWrote;
682 
683     int         WriteMIFHeader();
684     void UpdateExtents(double dfX,double dfY);
685 
686   public:
687     MIFFile();
688     virtual ~MIFFile();
689 
690     virtual TABFileClass GetFileClass() override {return TABFC_MIFFile;}
691 
692     virtual int Open(const char *pszFname, const char* pszAccess,
693                      GBool bTestOpenNoError = FALSE,
694                      const char* pszCharset = nullptr ) override { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError, pszCharset); }
695     virtual int Open(const char *pszFname, TABAccess eAccess,
696                      GBool bTestOpenNoError = FALSE,
697                      const char* pszCharset = nullptr ) override;
698     virtual int Close() override;
699 
700     virtual const char *GetTableName() override
701                            {return m_poDefn?m_poDefn->GetName():"";}
702 
703     virtual int         TestCapability( const char * pszCap ) override ;
704     virtual GIntBig     GetFeatureCount (int bForce) override;
705     virtual void        ResetReading() override;
706     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
707     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
708                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
709 
710     ///////////////
711     // Read access specific stuff
712     //
713 
714     virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
715     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
716     virtual OGRFeatureDefn *GetLayerDefn() override;
717 
718     virtual TABFieldType GetNativeFieldType(int nFieldId) override;
719 
720     virtual int GetBounds(double &dXMin, double &dYMin,
721                           double &dXMax, double &dYMax,
722                           GBool bForce = TRUE ) override;
723 
724     virtual OGRSpatialReference *GetSpatialRef() override;
725 
726     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
727                                       int &numRegions, int &numTexts,
728                                       GBool bForce = TRUE) override;
729 
730     virtual GBool IsFieldIndexed(int nFieldId) override;
731     virtual GBool IsFieldUnique(int nFieldId) override;
732 
733     virtual int GetVersion() { return m_nVersion; }
734 
735     ///////////////
736     // Write access specific stuff
737     //
738     virtual int SetBounds(double dXMin, double dYMin,
739                           double dXMax, double dYMax) override;
740     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
741                             TABFieldType *paeMapInfoNativeFieldTypes = nullptr) override;
742     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
743                                int nWidth=0, int nPrecision=0,
744                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
745                                int bApproxOK = TRUE) override;
746     /* TODO */
747     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
748 
749     virtual OGRErr CreateFeature(TABFeature *poFeature) override;
750 
751     virtual int SetFieldIndexed(int nFieldId) override;
752 
753     ///////////////
754     // semi-private.
755     virtual int  GetProjInfo(TABProjInfo * /*poPI*/) override{return -1;}
756     /*  { return m_poMAPFile->GetHeaderBlock()->GetProjInfo( poPI ); }*/
757     virtual int  SetProjInfo(TABProjInfo * /*poPI*/) override{return -1;}
758     /*  { return m_poMAPFile->GetHeaderBlock()->SetProjInfo( poPI ); }*/
759     virtual int  SetMIFCoordSys(const char * pszMIFCoordSys) override;
760     virtual int SetCharset(const char* pszCharset) override;
761 
762 #ifdef DEBUG
763     virtual void Dump(FILE * /*fpOut*/ = nullptr) override {}
764 #endif
765 };
766 
767 /*---------------------------------------------------------------------
768  * Define some error codes specific to this lib.
769  *--------------------------------------------------------------------*/
770 #define TAB_WarningFeatureTypeNotSupported     501
771 #define TAB_WarningInvalidFieldName            502
772 #define TAB_WarningBoundsOverflow              503
773 
774 /*---------------------------------------------------------------------
775  * Codes for the feature classes
776  *--------------------------------------------------------------------*/
777 typedef enum
778 {
779     TABFCNoGeomFeature = 0,
780     TABFCPoint = 1,
781     TABFCFontPoint = 2,
782     TABFCCustomPoint = 3,
783     TABFCText = 4,
784     TABFCPolyline = 5,
785     TABFCArc = 6,
786     TABFCRegion = 7,
787     TABFCRectangle = 8,
788     TABFCEllipse = 9,
789     TABFCMultiPoint = 10,
790     TABFCCollection = 11,
791     TABFCDebugFeature
792 } TABFeatureClass;
793 
794 /*---------------------------------------------------------------------
795  * Definitions for text attributes
796  *--------------------------------------------------------------------*/
797 typedef enum TABTextJust_t
798 {
799     TABTJLeft = 0,      // Default: Left Justification
800     TABTJCenter,
801     TABTJRight
802 } TABTextJust;
803 
804 typedef enum TABTextSpacing_t
805 {
806     TABTSSingle = 0,    // Default: Single spacing
807     TABTS1_5,           // 1.5
808     TABTSDouble
809 } TABTextSpacing;
810 
811 typedef enum TABTextLineType_t
812 {
813     TABTLNoLine = 0,    // Default: No line
814     TABTLSimple,
815     TABTLArrow
816 } TABTextLineType;
817 
818 typedef enum TABFontStyle_t     // Can be OR'ed
819 {                               // except box and halo are mutually exclusive
820     TABFSNone       = 0,
821     TABFSBold       = 0x0001,
822     TABFSItalic     = 0x0002,
823     TABFSUnderline  = 0x0004,
824     TABFSStrikeout  = 0x0008,
825     TABFSOutline    = 0x0010,
826     TABFSShadow     = 0x0020,
827     TABFSInverse    = 0x0040,
828     TABFSBlink      = 0x0080,
829     TABFSBox        = 0x0100,   // See note about box vs halo below.
830     TABFSHalo       = 0x0200,   // MIF uses 256, see MIF docs, App.A
831     TABFSAllCaps    = 0x0400,   // MIF uses 512
832     TABFSExpanded   = 0x0800    // MIF uses 1024
833 } TABFontStyle;
834 
835 /* TABFontStyle enum notes:
836  *
837  * The enumeration values above correspond to the values found in a .MAP
838  * file. However, they differ a little from what is found in a MIF file:
839  * Values 0x01 to 0x80 are the same in .MIF and .MAP files.
840  * Values 0x200 to 0x800 in .MAP are 0x100 to 0x400 in .MIF
841  *
842  * What about TABFSBox (0x100) ?
843  * TABFSBox is stored just like the other styles in .MAP files but it is not
844  * explicitly stored in a MIF file.
845  * If a .MIF FONT() clause contains the optional BG color, then this implies
846  * that either Halo or Box was set.  Thus if TABFSHalo (value 256 in MIF)
847  * is not set in the style, then this implies that TABFSBox should be set.
848  */
849 
850 typedef enum TABCustSymbStyle_t // Can be OR'ed
851 {
852     TABCSNone       = 0,        // Transparent BG, use default colors
853     TABCSBGOpaque   = 0x01,     // White pixels are opaque
854     TABCSApplyColor = 0x02      // non-white pixels drawn using symbol color
855 } TABCustSymbStyle;
856 
857 /*=====================================================================
858   Base classes to be used to add supported drawing tools to each feature type
859  =====================================================================*/
860 
861 class ITABFeaturePen
862 {
863   protected:
864     int         m_nPenDefIndex;
865     TABPenDef   m_sPenDef;
866   public:
867     ITABFeaturePen();
868     virtual ~ITABFeaturePen() {}
869     int         GetPenDefIndex() const {return m_nPenDefIndex;}
870     TABPenDef  *GetPenDefRef() {return &m_sPenDef;}
871     const TABPenDef  *GetPenDefRef() const {return &m_sPenDef;}
872 
873     GByte       GetPenWidthPixel() const;
874     double      GetPenWidthPoint() const;
875     int         GetPenWidthMIF() const;
876     GByte       GetPenPattern() const {return m_sPenDef.nLinePattern;}
877     GInt32      GetPenColor() const   {return m_sPenDef.rgbColor;}
878 
879     void        SetPenWidthPixel(GByte val);
880     void        SetPenWidthPoint(double val);
881     void        SetPenWidthMIF(int val);
882 
883     void        SetPenPattern(GByte val) {m_sPenDef.nLinePattern=val;}
884     void        SetPenColor(GInt32 clr)  {m_sPenDef.rgbColor = clr;}
885 
886     const char *GetPenStyleString() const;
887     void        SetPenFromStyleString(const char *pszStyleString);
888 
889     void        DumpPenDef(FILE *fpOut = nullptr);
890 };
891 
892 class ITABFeatureBrush
893 {
894   protected:
895     int         m_nBrushDefIndex;
896     TABBrushDef m_sBrushDef;
897   public:
898     ITABFeatureBrush();
899     virtual ~ITABFeatureBrush() {}
900     int         GetBrushDefIndex() const {return m_nBrushDefIndex;}
901     TABBrushDef *GetBrushDefRef() {return &m_sBrushDef;}
902     const TABBrushDef *GetBrushDefRef() const {return &m_sBrushDef;}
903 
904     GInt32      GetBrushFGColor() const     {return m_sBrushDef.rgbFGColor;}
905     GInt32      GetBrushBGColor() const     {return m_sBrushDef.rgbBGColor;}
906     GByte       GetBrushPattern() const     {return m_sBrushDef.nFillPattern;}
907     GByte       GetBrushTransparent() const {return m_sBrushDef.bTransparentFill;}
908 
909     void        SetBrushFGColor(GInt32 clr)  { m_sBrushDef.rgbFGColor = clr;}
910     void        SetBrushBGColor(GInt32 clr)  { m_sBrushDef.rgbBGColor = clr;}
911     void        SetBrushPattern(GByte val)   { m_sBrushDef.nFillPattern=val;}
912     void        SetBrushTransparent(GByte val)
913                                           {m_sBrushDef.bTransparentFill=val;}
914 
915     const char *GetBrushStyleString() const;
916     void        SetBrushFromStyleString(const char *pszStyleString);
917 
918     void        DumpBrushDef(FILE *fpOut = nullptr);
919 };
920 
921 class ITABFeatureFont
922 {
923   protected:
924     int         m_nFontDefIndex;
925     TABFontDef  m_sFontDef;
926   public:
927     ITABFeatureFont();
928     virtual ~ITABFeatureFont() {}
929     int         GetFontDefIndex() const {return m_nFontDefIndex;}
930     TABFontDef *GetFontDefRef() {return &m_sFontDef;}
931     const TABFontDef *GetFontDefRef() const {return &m_sFontDef;}
932 
933     const char *GetFontNameRef() const {return m_sFontDef.szFontName;}
934 
935     void        SetFontName(const char *pszName);
936 
937     void        DumpFontDef(FILE *fpOut = nullptr);
938 };
939 
940 class ITABFeatureSymbol
941 {
942   protected:
943     int         m_nSymbolDefIndex;
944     TABSymbolDef m_sSymbolDef;
945   public:
946     ITABFeatureSymbol();
947     virtual ~ITABFeatureSymbol() {}
948     int         GetSymbolDefIndex() const {return m_nSymbolDefIndex;}
949     TABSymbolDef *GetSymbolDefRef() {return &m_sSymbolDef;}
950     const TABSymbolDef *GetSymbolDefRef() const {return &m_sSymbolDef;}
951 
952     GInt16      GetSymbolNo() const    {return m_sSymbolDef.nSymbolNo;}
953     GInt16      GetSymbolSize() const  {return m_sSymbolDef.nPointSize;}
954     GInt32      GetSymbolColor() const {return m_sSymbolDef.rgbColor;}
955 
956     void        SetSymbolNo(GInt16 val)     { m_sSymbolDef.nSymbolNo = val;}
957     void        SetSymbolSize(GInt16 val)   { m_sSymbolDef.nPointSize = val;}
958     void        SetSymbolColor(GInt32 clr)  { m_sSymbolDef.rgbColor = clr;}
959 
960     static TABFeatureClass GetSymbolFeatureClass(const char *pszStyleString);
961     virtual const char *GetSymbolStyleString(double dfAngle = 0.0) const;
962     void        SetSymbolFromStyleString(const char *pszStyleString);
963     virtual void SetSymbolFromStyle(OGRStyleSymbol* poSymbolStyle);
964 
965     void        DumpSymbolDef(FILE *fpOut = nullptr);
966 };
967 
968 /*=====================================================================
969                         Feature Classes
970  =====================================================================*/
971 
972 /*---------------------------------------------------------------------
973  *                      class TABFeature
974  *
975  * Extend the OGRFeature to support MapInfo specific extensions related
976  * to geometry types, representation strings, etc.
977  *
978  * TABFeature will be used as a base class for all the feature classes.
979  *
980  * This class will also be used to instantiate objects with no Geometry
981  * (i.e. type TAB_GEOM_NONE) which is a valid case in MapInfo.
982  *
983  * The logic to read/write the object from/to the .DAT and .MAP files is also
984  * implemented as part of this class and derived classes.
985  *--------------------------------------------------------------------*/
986 class TABFeature : public OGRFeature
987 {
988   protected:
989     TABGeomType m_nMapInfoType;
990 
991     double      m_dXMin;
992     double      m_dYMin;
993     double      m_dXMax;
994     double      m_dYMax;
995 
996     GBool       m_bDeletedFlag;
997 
998     void        CopyTABFeatureBase(TABFeature *poDestFeature);
999 
1000     // Compr. Origin is set for TAB files by ValidateCoordType()
1001     GInt32      m_nXMin;
1002     GInt32      m_nYMin;
1003     GInt32      m_nXMax;
1004     GInt32      m_nYMax;
1005     GInt32      m_nComprOrgX;
1006     GInt32      m_nComprOrgY;
1007 
1008     virtual int UpdateMBR(TABMAPFile *poMapFile = nullptr);
1009 
1010   public:
1011     explicit TABFeature(OGRFeatureDefn *poDefnIn );
1012     virtual ~TABFeature();
1013 
1014     static  TABFeature     *CreateFromMapInfoType(int nMapInfoType,
1015                                                   OGRFeatureDefn *poDefn);
1016 
1017     virtual TABFeature     *CloneTABFeature(OGRFeatureDefn *pNewDefn = nullptr);
1018     virtual TABFeatureClass GetFeatureClass() { return TABFCNoGeomFeature; }
1019     virtual TABGeomType     GetMapInfoType()  { return m_nMapInfoType; }
1020     virtual TABGeomType     ValidateMapInfoType(CPL_UNUSED TABMAPFile *poMapFile = nullptr)
1021                                                 {m_nMapInfoType=TAB_GEOM_NONE;
1022                                                  return m_nMapInfoType;}
1023     GBool       IsRecordDeleted() { return m_bDeletedFlag; }
1024     void        SetRecordDeleted(GBool bDeleted) { m_bDeletedFlag=bDeleted; }
1025 
1026     /*-----------------------------------------------------------------
1027      * TAB Support
1028      *----------------------------------------------------------------*/
1029 
1030     virtual int ReadRecordFromDATFile(TABDATFile *poDATFile);
1031     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1032                                         GBool bCoordDataOnly=FALSE,
1033                                         TABMAPCoordBlock **ppoCoordBlock=nullptr);
1034 
1035     virtual int WriteRecordToDATFile(TABDATFile *poDATFile,
1036                                      TABINDFile *poINDFile, int *panIndexNo);
1037     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1038                                        GBool bCoordDataOnly=FALSE,
1039                                        TABMAPCoordBlock **ppoCoordBlock=nullptr);
1040     GBool       ValidateCoordType(TABMAPFile * poMapFile);
1041     void        ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
1042                                         GInt32 nComprOrgX, GInt32 nComprOrgY,
1043                                         GInt32 nXMin, GInt32 nYMin,
1044                                         GInt32 nXMax, GInt32 nYMax);
1045 
1046     /*-----------------------------------------------------------------
1047      * Mid/Mif Support
1048      *----------------------------------------------------------------*/
1049 
1050     virtual int ReadRecordFromMIDFile(MIDDATAFile *fp);
1051     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
1052 
1053     virtual int WriteRecordToMIDFile(MIDDATAFile *fp);
1054     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
1055 
1056     void ReadMIFParameters(MIDDATAFile *fp);
1057     void WriteMIFParameters(MIDDATAFile *fp);
1058 
1059     /*-----------------------------------------------------------------
1060      *----------------------------------------------------------------*/
1061 
1062     void        SetMBR(double dXMin, double dYMin,
1063                        double dXMax, double dYMax);
1064     void        GetMBR(double &dXMin, double &dYMin,
1065                        double &dXMax, double &dYMax);
1066     void        SetIntMBR(GInt32 nXMin, GInt32 nYMin,
1067                           GInt32 nXMax, GInt32 nYMax);
1068     void        GetIntMBR(GInt32 &nXMin, GInt32 &nYMin,
1069                           GInt32 &nXMax, GInt32 &nYMax);
1070 
1071     virtual void DumpMID(FILE *fpOut = nullptr);
1072     virtual void DumpMIF(FILE *fpOut = nullptr);
1073 };
1074 
1075 /*---------------------------------------------------------------------
1076  *                      class TABPoint
1077  *
1078  * Feature class to handle old style MapInfo point symbols:
1079  *
1080  *     TAB_GEOM_SYMBOL_C        0x01
1081  *     TAB_GEOM_SYMBOL          0x02
1082  *
1083  * Feature geometry will be a OGRPoint
1084  *
1085  * The symbol number is in the range [31..67], with 31=None and corresponds
1086  * to one of the 35 predefined "Old MapInfo Symbols"
1087  *
1088  * NOTE: This class is also used as a base class for the other point
1089  * symbol types TABFontPoint and TABCustomPoint.
1090  *--------------------------------------------------------------------*/
1091 class TABPoint: public TABFeature,
1092                 public ITABFeatureSymbol
1093 {
1094     CPL_DISALLOW_COPY_ASSIGN(TABPoint)
1095 
1096   public:
1097     explicit TABPoint(OGRFeatureDefn *poDefnIn);
1098     virtual ~TABPoint();
1099 
1100     virtual TABFeatureClass GetFeatureClass() override { return TABFCPoint; }
1101     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1102 
1103     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1104 
1105     double      GetX();
1106     double      GetY();
1107 
1108     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1109                                         GBool bCoordDataOnly=FALSE,
1110                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1111     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1112                                        GBool bCoordDataOnly=FALSE,
1113                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1114 
1115     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1116     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1117 
1118     virtual const char *GetStyleString() const override;
1119 
1120     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1121 };
1122 
1123 /*---------------------------------------------------------------------
1124  *                      class TABFontPoint
1125  *
1126  * Feature class to handle MapInfo Font Point Symbol types:
1127  *
1128  *     TAB_GEOM_FONTSYMBOL_C    0x28
1129  *     TAB_GEOM_FONTSYMBOL      0x29
1130  *
1131  * Feature geometry will be a OGRPoint
1132  *
1133  * The symbol number refers to a character code in the specified Windows
1134  * Font (e.g. "Windings").
1135  *--------------------------------------------------------------------*/
1136 class TABFontPoint final : public TABPoint,
1137                     public ITABFeatureFont
1138 {
1139     CPL_DISALLOW_COPY_ASSIGN(TABFontPoint)
1140 
1141   protected:
1142     double      m_dAngle;
1143     GInt16      m_nFontStyle;           // Bold/shadow/halo/etc.
1144 
1145   public:
1146     explicit TABFontPoint(OGRFeatureDefn *poDefnIn);
1147     virtual ~TABFontPoint();
1148 
1149     virtual TABFeatureClass GetFeatureClass() override { return TABFCFontPoint; }
1150 
1151     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1152 
1153     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1154                                         GBool bCoordDataOnly=FALSE,
1155                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1156     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1157                                        GBool bCoordDataOnly=FALSE,
1158                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1159 
1160     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1161     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1162 
1163     virtual const char *GetSymbolStyleString(double dfAngle = 0.0) const override;
1164     virtual const char *GetStyleString() const override;
1165     virtual void SetSymbolFromStyle(OGRStyleSymbol* poSymbolStyle) override;
1166 
1167     GBool       QueryFontStyle(TABFontStyle eStyleToQuery);
1168     void        ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStatus);
1169 
1170     int         GetFontStyleMIFValue();
1171     void        SetFontStyleMIFValue(int nStyle);
1172     int         GetFontStyleTABValue()           {return m_nFontStyle;}
1173     void        SetFontStyleTABValue(int nStyle){m_nFontStyle=static_cast<GInt16>(nStyle);}
1174 
1175     // GetSymbolAngle(): Return angle in degrees counterclockwise
1176     double      GetSymbolAngle() const {return m_dAngle;}
1177     void        SetSymbolAngle(double dAngle);
1178 };
1179 
1180 /*---------------------------------------------------------------------
1181  *                      class TABCustomPoint
1182  *
1183  * Feature class to handle MapInfo Custom Point Symbol (Bitmap) types:
1184  *
1185  *     TAB_GEOM_CUSTOMSYMBOL_C  0x2b
1186  *     TAB_GEOM_CUSTOMSYMBOL    0x2c
1187  *
1188  * Feature geometry will be a OGRPoint
1189  *
1190  * The symbol name is the name of a BMP file stored in the "CustSymb"
1191  * directory (e.g. "arrow.BMP").  The symbol number has no meaning for
1192  * this symbol type.
1193  *--------------------------------------------------------------------*/
1194 class TABCustomPoint final : public TABPoint,
1195                       public ITABFeatureFont
1196 {
1197   protected:
1198     GByte       m_nCustomStyle;         // Show BG/Apply Color
1199 
1200   public:
1201     GByte       m_nUnknown_;
1202 
1203   public:
1204     explicit TABCustomPoint(OGRFeatureDefn *poDefnIn);
1205     virtual ~TABCustomPoint();
1206 
1207     virtual TABFeatureClass GetFeatureClass() override { return TABFCCustomPoint; }
1208 
1209     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1210 
1211     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1212                                         GBool bCoordDataOnly=FALSE,
1213                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1214     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1215                                        GBool bCoordDataOnly=FALSE,
1216                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1217 
1218     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1219     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1220 
1221     virtual const char *GetSymbolStyleString(double dfAngle = 0.0) const override;
1222     virtual const char *GetStyleString() const override;
1223     virtual void SetSymbolFromStyle(OGRStyleSymbol* poSymbolStyle) override;
1224 
1225     const char *GetSymbolNameRef() const { return GetFontNameRef(); }
1226     void        SetSymbolName(const char *pszName) {SetFontName(pszName);}
1227 
1228     GByte       GetCustomSymbolStyle()              {return m_nCustomStyle;}
1229     void        SetCustomSymbolStyle(GByte nStyle)  {m_nCustomStyle = nStyle;}
1230 };
1231 
1232 /*---------------------------------------------------------------------
1233  *                      class TABPolyline
1234  *
1235  * Feature class to handle the various MapInfo line types:
1236  *
1237  *     TAB_GEOM_LINE_C         0x04
1238  *     TAB_GEOM_LINE           0x05
1239  *     TAB_GEOM_PLINE_C        0x07
1240  *     TAB_GEOM_PLINE          0x08
1241  *     TAB_GEOM_MULTIPLINE_C   0x25
1242  *     TAB_GEOM_MULTIPLINE     0x26
1243  *     TAB_GEOM_V450_MULTIPLINE_C 0x31
1244  *     TAB_GEOM_V450_MULTIPLINE   0x32
1245  *
1246  * Feature geometry can be either a OGRLineString or a OGRMultiLineString
1247  *--------------------------------------------------------------------*/
1248 class TABPolyline final : public TABFeature,
1249                    public ITABFeaturePen
1250 {
1251   private:
1252     GBool       m_bCenterIsSet;
1253     double      m_dCenterX;
1254     double      m_dCenterY;
1255     GBool       m_bWriteTwoPointLineAsPolyline;
1256 
1257   public:
1258     explicit TABPolyline(OGRFeatureDefn *poDefnIn);
1259     virtual ~TABPolyline();
1260 
1261     virtual TABFeatureClass GetFeatureClass() override { return TABFCPolyline; }
1262     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1263 
1264     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1265 
1266     /* 2 methods to simplify access to rings in a multiple polyline
1267      */
1268     int                 GetNumParts();
1269     OGRLineString      *GetPartRef(int nPartIndex);
1270 
1271     GBool       TwoPointLineAsPolyline();
1272     void        TwoPointLineAsPolyline(GBool bTwoPointLineAsPolyline);
1273 
1274     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1275                                         GBool bCoordDataOnly=FALSE,
1276                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1277     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1278                                        GBool bCoordDataOnly=FALSE,
1279                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1280 
1281     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1282     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1283 
1284     virtual const char *GetStyleString() const override;
1285 
1286     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1287 
1288     int         GetCenter(double &dX, double &dY);
1289     void        SetCenter(double dX, double dY);
1290 
1291     // MapInfo-specific attributes... made available through public vars
1292     // for now.
1293     GBool       m_bSmooth;
1294 };
1295 
1296 /*---------------------------------------------------------------------
1297  *                      class TABRegion
1298  *
1299  * Feature class to handle the MapInfo region types:
1300  *
1301  *     TAB_GEOM_REGION_C         0x0d
1302  *     TAB_GEOM_REGION           0x0e
1303  *     TAB_GEOM_V450_REGION_C    0x2e
1304  *     TAB_GEOM_V450_REGION      0x2f
1305  *
1306  * Feature geometry will be returned as OGRPolygon (with a single ring)
1307  * or OGRMultiPolygon (for multiple rings).
1308  *
1309  * REGIONs with multiple rings are returned as OGRMultiPolygon instead of
1310  * as OGRPolygons since OGRPolygons require that the first ring be the
1311  * outer ring, and the other all be inner rings, but this is not guaranteed
1312  * inside MapInfo files.  However, when writing features, OGRPolygons with
1313  * multiple rings will be accepted without problem.
1314  *--------------------------------------------------------------------*/
1315 class TABRegion final : public TABFeature,
1316                  public ITABFeaturePen,
1317                  public ITABFeatureBrush
1318 {
1319   private:
1320     GBool       m_bSmooth;
1321     GBool       m_bCenterIsSet;
1322     double      m_dCenterX;
1323     double      m_dCenterY;
1324 
1325     int     ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
1326                             TABMAPFile *poMAPFile);
1327     static int     AppendSecHdrs(OGRPolygon *poPolygon,
1328                           TABMAPCoordSecHdr * &pasSecHdrs,
1329                           TABMAPFile *poMAPFile,
1330                           int &iLastRing);
1331 
1332   public:
1333     explicit TABRegion(OGRFeatureDefn *poDefnIn);
1334     virtual ~TABRegion();
1335 
1336     virtual TABFeatureClass GetFeatureClass() override { return TABFCRegion; }
1337     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1338 
1339     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1340 
1341     /* 2 methods to make the REGION's geometry look like a single collection
1342      * of OGRLinearRings
1343      */
1344     int                 GetNumRings();
1345     OGRLinearRing      *GetRingRef(int nRequestedRingIndex);
1346     GBool               IsInteriorRing(int nRequestedRingIndex);
1347 
1348     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1349                                         GBool bCoordDataOnly=FALSE,
1350                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1351     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1352                                        GBool bCoordDataOnly=FALSE,
1353                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1354 
1355     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1356     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1357 
1358     virtual const char *GetStyleString() const override;
1359 
1360     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1361 
1362     int         GetCenter(double &dX, double &dY);
1363     void        SetCenter(double dX, double dY);
1364 };
1365 
1366 /*---------------------------------------------------------------------
1367  *                      class TABRectangle
1368  *
1369  * Feature class to handle the MapInfo rectangle types:
1370  *
1371  *     TAB_GEOM_RECT_C         0x13
1372  *     TAB_GEOM_RECT           0x14
1373  *     TAB_GEOM_ROUNDRECT_C    0x16
1374  *     TAB_GEOM_ROUNDRECT      0x17
1375  *
1376  * A rectangle is defined by the coords of its 2 opposite corners (the MBR)
1377  * Its corners can optionally be rounded, in which case a X and Y rounding
1378  * radius will be defined.
1379  *
1380  * Feature geometry will be OGRPolygon
1381  *--------------------------------------------------------------------*/
1382 class TABRectangle final : public TABFeature,
1383                     public ITABFeaturePen,
1384                     public ITABFeatureBrush
1385 {
1386   private:
1387     virtual int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1388 
1389   public:
1390     explicit TABRectangle(OGRFeatureDefn *poDefnIn);
1391     virtual ~TABRectangle();
1392 
1393     virtual TABFeatureClass GetFeatureClass() override { return TABFCRectangle; }
1394     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1395 
1396     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1397 
1398     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1399                                         GBool bCoordDataOnly=FALSE,
1400                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1401     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1402                                        GBool bCoordDataOnly=FALSE,
1403                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1404 
1405     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1406     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1407 
1408     virtual const char *GetStyleString() const override;
1409 
1410     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1411 
1412     // MapInfo-specific attributes... made available through public vars
1413     // for now.
1414     GBool       m_bRoundCorners;
1415     double      m_dRoundXRadius;
1416     double      m_dRoundYRadius;
1417 };
1418 
1419 /*---------------------------------------------------------------------
1420  *                      class TABEllipse
1421  *
1422  * Feature class to handle the MapInfo ellipse types:
1423  *
1424  *     TAB_GEOM_ELLIPSE_C      0x19
1425  *     TAB_GEOM_ELLIPSE        0x1a
1426  *
1427  * An ellipse is defined by the coords of its 2 opposite corners (the MBR)
1428  *
1429  * Feature geometry can be either an OGRPoint defining the center of the
1430  * ellipse, or an OGRPolygon defining the ellipse itself.
1431  *
1432  * When an ellipse is read, the returned geometry is a OGRPolygon representing
1433  * the ellipse with 2 degrees line segments.
1434  *
1435  * In the case of the OGRPoint, then the X/Y Radius MUST be set, but.
1436  * However with an OGRPolygon, if the X/Y radius are not set (== 0) then
1437  * the MBR of the polygon will be used to define the ellipse parameters
1438  * and the center of the MBR is used as the center of the ellipse...
1439  * (i.e. the polygon vertices themselves will be ignored).
1440  *--------------------------------------------------------------------*/
1441 class TABEllipse final : public TABFeature,
1442                   public ITABFeaturePen,
1443                   public ITABFeatureBrush
1444 {
1445   private:
1446     virtual int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1447 
1448   public:
1449     explicit TABEllipse(OGRFeatureDefn *poDefnIn);
1450     virtual ~TABEllipse();
1451 
1452     virtual TABFeatureClass GetFeatureClass() override { return TABFCEllipse; }
1453     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1454 
1455     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1456 
1457     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1458                                         GBool bCoordDataOnly=FALSE,
1459                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1460     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1461                                        GBool bCoordDataOnly=FALSE,
1462                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1463 
1464     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1465     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1466 
1467     virtual const char *GetStyleString() const override;
1468 
1469     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1470 
1471     // MapInfo-specific attributes... made available through public vars
1472     // for now.
1473     double      m_dCenterX;
1474     double      m_dCenterY;
1475     double      m_dXRadius;
1476     double      m_dYRadius;
1477 };
1478 
1479 /*---------------------------------------------------------------------
1480  *                      class TABArc
1481  *
1482  * Feature class to handle the MapInfo arc types:
1483  *
1484  *     TAB_GEOM_ARC_C      0x0a
1485  *     TAB_GEOM_ARC        0x0b
1486  *
1487  * In MapInfo, an arc is defined by the coords of the MBR corners of its
1488  * defining ellipse, which in this case is different from the arc's MBR,
1489  * and a start and end angle in degrees.
1490  *
1491  * Feature geometry can be either an OGRLineString or an OGRPoint.
1492  *
1493  * In any case, X/Y radius X/Y center, and start/end angle (in degrees
1494  * counterclockwise) MUST be set.
1495  *
1496  * When an arc is read, the returned geometry is an OGRLineString
1497  * representing the arc with 2 degrees line segments.
1498  *--------------------------------------------------------------------*/
1499 class TABArc final : public TABFeature,
1500               public ITABFeaturePen
1501 {
1502   private:
1503     double      m_dStartAngle;  // In degrees, counterclockwise,
1504     double      m_dEndAngle;    // starting at 3 o'clock
1505 
1506     virtual int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1507 
1508   public:
1509     explicit TABArc(OGRFeatureDefn *poDefnIn);
1510     virtual ~TABArc();
1511 
1512     virtual TABFeatureClass GetFeatureClass() override { return TABFCArc; }
1513     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1514 
1515     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1516 
1517     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1518                                         GBool bCoordDataOnly=FALSE,
1519                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1520     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1521                                        GBool bCoordDataOnly=FALSE,
1522                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1523 
1524     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1525     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1526 
1527     virtual const char *GetStyleString() const override;
1528 
1529     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1530 
1531     double      GetStartAngle() { return m_dStartAngle; }
1532     double      GetEndAngle()   { return m_dEndAngle; }
1533     void        SetStartAngle(double dAngle);
1534     void        SetEndAngle(double dAngle);
1535 
1536     // MapInfo-specific attributes... made available through public vars
1537     // for now.
1538     double      m_dCenterX;
1539     double      m_dCenterY;
1540     double      m_dXRadius;
1541     double      m_dYRadius;
1542 };
1543 
1544 /*---------------------------------------------------------------------
1545  *                      class TABText
1546  *
1547  * Feature class to handle the MapInfo text types:
1548  *
1549  *     TAB_GEOM_TEXT_C         0x10
1550  *     TAB_GEOM_TEXT           0x11
1551  *
1552  * Feature geometry is an OGRPoint corresponding to the lower-left
1553  * corner of the text MBR BEFORE ROTATION.
1554  *
1555  * Text string, and box height/width (box before rotation is applied)
1556  * are required in a valid text feature and MUST be set.
1557  * Text angle and other styles are optional.
1558  *--------------------------------------------------------------------*/
1559 class TABText final : public TABFeature,
1560                public ITABFeatureFont,
1561                public ITABFeaturePen
1562 {
1563     CPL_DISALLOW_COPY_ASSIGN(TABText)
1564 
1565   protected:
1566     char        *m_pszString;
1567 
1568     double      m_dAngle;
1569     double      m_dHeight;
1570     mutable double      m_dWidth;
1571     double      m_dfLineEndX;
1572     double      m_dfLineEndY;
1573     GBool       m_bLineEndSet;
1574     void        UpdateTextMBR();
1575 
1576     GInt32      m_rgbForeground;
1577     GInt32      m_rgbBackground;
1578     GInt32      m_rgbOutline;
1579     GInt32      m_rgbShadow;
1580 
1581     GInt16      m_nTextAlignment;       // Justification/Vert.Spacing/arrow
1582     GInt16      m_nFontStyle;           // Bold/italic/underlined/shadow/...
1583 
1584     const char *GetLabelStyleString() const;
1585 
1586     virtual int UpdateMBR(TABMAPFile *poMapFile = nullptr) override;
1587 
1588   public:
1589     explicit TABText(OGRFeatureDefn *poDefnIn);
1590     virtual ~TABText();
1591 
1592     virtual TABFeatureClass GetFeatureClass() override { return TABFCText; }
1593     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1594 
1595     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1596 
1597     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1598                                         GBool bCoordDataOnly=FALSE,
1599                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1600     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1601                                        GBool bCoordDataOnly=FALSE,
1602                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1603 
1604     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1605     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1606 
1607     virtual const char *GetStyleString() const override;
1608 
1609     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1610 
1611     const char *GetTextString() const;
1612     double      GetTextAngle() const;
1613     double      GetTextBoxHeight() const;
1614     double      GetTextBoxWidth() const;
1615     GInt32      GetFontFGColor() const;
1616     GInt32      GetFontBGColor() const;
1617     GInt32      GetFontOColor() const;
1618     GInt32      GetFontSColor() const;
1619     void        GetTextLineEndPoint(double &dX, double &dY);
1620 
1621     TABTextJust GetTextJustification() const;
1622     TABTextSpacing  GetTextSpacing() const;
1623     TABTextLineType GetTextLineType() const;
1624     GBool       QueryFontStyle(TABFontStyle eStyleToQuery) const;
1625 
1626     void        SetTextString(const char *pszStr);
1627     void        SetTextAngle(double dAngle);
1628     void        SetTextBoxHeight(double dHeight);
1629     void        SetTextBoxWidth(double dWidth);
1630     void        SetFontFGColor(GInt32 rgbColor);
1631     void        SetFontBGColor(GInt32 rgbColor);
1632     void        SetFontOColor(GInt32 rgbColor);
1633     void        SetFontSColor(GInt32 rgbColor);
1634     void        SetTextLineEndPoint(double dX, double dY);
1635 
1636     void        SetTextJustification(TABTextJust eJust);
1637     void        SetTextSpacing(TABTextSpacing eSpacing);
1638     void        SetTextLineType(TABTextLineType eLineType);
1639     void        ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStatus);
1640 
1641     int         GetFontStyleMIFValue() const;
1642     void        SetFontStyleMIFValue(int nStyle, GBool bBGColorSet=FALSE);
1643     GBool       IsFontBGColorUsed() const;
1644     GBool       IsFontOColorUsed() const;
1645     GBool       IsFontSColorUsed() const;
1646     GBool       IsFontBold() const;
1647     GBool       IsFontItalic() const;
1648     GBool       IsFontUnderline() const;
1649     int         GetFontStyleTABValue() const {return m_nFontStyle;}
1650     void        SetFontStyleTABValue(int nStyle){m_nFontStyle=static_cast<GInt16>(nStyle);}
1651 };
1652 
1653 /*---------------------------------------------------------------------
1654  *                      class TABMultiPoint
1655  *
1656  * Feature class to handle MapInfo Multipoint features:
1657  *
1658  *     TAB_GEOM_MULTIPOINT_C        0x34
1659  *     TAB_GEOM_MULTIPOINT          0x35
1660  *
1661  * Feature geometry will be a OGRMultiPoint
1662  *
1663  * The symbol number is in the range [31..67], with 31=None and corresponds
1664  * to one of the 35 predefined "Old MapInfo Symbols"
1665  *--------------------------------------------------------------------*/
1666 class TABMultiPoint final : public TABFeature,
1667                      public ITABFeatureSymbol
1668 {
1669   private:
1670     // We call it center, but it is more like a label point
1671     // Its value default to be the location of the first point
1672     GBool       m_bCenterIsSet;
1673     double      m_dCenterX;
1674     double      m_dCenterY;
1675 
1676   public:
1677     explicit TABMultiPoint(OGRFeatureDefn *poDefnIn);
1678     virtual ~TABMultiPoint();
1679 
1680     virtual TABFeatureClass GetFeatureClass() override { return TABFCMultiPoint; }
1681     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1682 
1683     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1684 
1685     int         GetXY(int i, double &dX, double &dY);
1686     int         GetNumPoints();
1687 
1688     int         GetCenter(double &dX, double &dY);
1689     void        SetCenter(double dX, double dY);
1690 
1691     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1692                                         GBool bCoordDataOnly=FALSE,
1693                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1694     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1695                                        GBool bCoordDataOnly=FALSE,
1696                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1697 
1698     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1699     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1700 
1701     virtual const char *GetStyleString() const override;
1702 
1703     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1704 };
1705 
1706 /*---------------------------------------------------------------------
1707  *
1708  *                      class TABCollection
1709  *
1710  * Feature class to handle MapInfo Collection features:
1711  *
1712  *     TAB_GEOM_COLLECTION_C        0x37
1713  *     TAB_GEOM_COLLECTION          0x38
1714  *
1715  * Feature geometry will be a OGRCollection
1716  *
1717  * **** IMPORTANT NOTE: ****
1718  *
1719  * The current implementation does not allow setting the Geometry via
1720  * OGRFeature::SetGeometry*(). The geometries must be set via the
1721  * TABCollection::SetRegion/Pline/MpointDirectly() methods which will take
1722  * care of keeping the OGRFeature's geometry in sync.
1723  *
1724  * If we ever want to support creating collections via the OGR interface then
1725  * something should be added in TABCollection::WriteGeometryToMapFile(), or
1726  * perhaps in ValidateMapInfoType(), or even better in a custom
1727  * TABCollection::SetGeometry*()... but then this last option may not work
1728  * unless OGRFeature::SetGeometry*() are made virtual in OGR.
1729  *
1730  *--------------------------------------------------------------------*/
1731 class TABCollection final : public TABFeature,
1732                      public ITABFeatureSymbol
1733 {
1734     CPL_DISALLOW_COPY_ASSIGN(TABCollection)
1735 
1736   private:
1737     TABRegion       *m_poRegion;
1738     TABPolyline     *m_poPline;
1739     TABMultiPoint   *m_poMpoint;
1740 
1741     void    EmptyCollection();
1742     static int     ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
1743                             GBool bComprCoord,
1744                             GInt32 nComprOrgX, GInt32 nComprOrgY,
1745                             GInt32 &pnMinX, GInt32 &pnMinY,
1746                             GInt32 &pnMaxX, GInt32 &pnMaxY,
1747                             GInt32 &pnLabelX, GInt32 &pnLabelY );
1748     static int     WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
1749                              GBool bComprCoord,
1750                              GInt32 nMinX, GInt32 nMinY,
1751                              GInt32 nMaxX, GInt32 nMaxY,
1752                              GInt32 nLabelX, GInt32 nLabelY );
1753     int     SyncOGRGeometryCollection(GBool bSyncRegion,
1754                                       GBool bSyncPline,
1755                                       GBool bSyncMpoint);
1756 
1757   public:
1758     explicit TABCollection(OGRFeatureDefn *poDefnIn);
1759     virtual ~TABCollection();
1760 
1761     virtual TABFeatureClass GetFeatureClass() override { return TABFCCollection; }
1762     virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = nullptr) override;
1763 
1764     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = nullptr ) override;
1765 
1766     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1767                                         GBool bCoordDataOnly=FALSE,
1768                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1769     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1770                                        GBool bCoordDataOnly=FALSE,
1771                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1772 
1773     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1774     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1775 
1776     virtual const char *GetStyleString() const override;
1777 
1778     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1779 
1780     TABRegion           *GetRegionRef()         {return m_poRegion; }
1781     TABPolyline         *GetPolylineRef()       {return m_poPline; }
1782     TABMultiPoint       *GetMultiPointRef()     {return m_poMpoint; }
1783 
1784     int                 SetRegionDirectly(TABRegion *poRegion);
1785     int                 SetPolylineDirectly(TABPolyline *poPline);
1786     int                 SetMultiPointDirectly(TABMultiPoint *poMpoint);
1787 };
1788 
1789 /*---------------------------------------------------------------------
1790  *                      class TABDebugFeature
1791  *
1792  * Feature class to use for testing purposes... this one does not
1793  * correspond to any MapInfo type... it is just used to dump info about
1794  * feature types that are not implemented yet.
1795  *--------------------------------------------------------------------*/
1796 class TABDebugFeature final : public TABFeature
1797 {
1798   private:
1799     GByte       m_abyBuf[512];
1800     int         m_nSize;
1801     int         m_nCoordDataPtr;  // -1 if none
1802     int         m_nCoordDataSize;
1803 
1804   public:
1805     explicit TABDebugFeature(OGRFeatureDefn *poDefnIn);
1806     virtual ~TABDebugFeature();
1807 
1808     virtual TABFeatureClass GetFeatureClass() override { return TABFCDebugFeature; }
1809 
1810     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1811                                         GBool bCoordDataOnly=FALSE,
1812                                         TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1813     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
1814                                        GBool bCoordDataOnly=FALSE,
1815                                        TABMAPCoordBlock **ppoCoordBlock=nullptr) override;
1816 
1817     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
1818     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
1819 
1820     virtual void DumpMIF(FILE *fpOut = nullptr) override;
1821 };
1822 
1823 /* -------------------------------------------------------------------- */
1824 /*      Some stuff related to spatial reference system handling.        */
1825 /*                                                                      */
1826 /*      In GDAL we make use of the coordsys transformation from         */
1827 /*      other places (sometimes even from plugins), so we               */
1828 /*      deliberately export these two functions from the DLL.           */
1829 /* -------------------------------------------------------------------- */
1830 
1831 char CPL_DLL *MITABSpatialRef2CoordSys( const OGRSpatialReference * );
1832 OGRSpatialReference CPL_DLL * MITABCoordSys2SpatialRef( const char * );
1833 
1834 bool MITABExtractCoordSysBounds( const char * pszCoordSys,
1835                                  double &dXMin, double &dYMin,
1836                                  double &dXMax, double &dYMax );
1837 int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj);
1838 
1839 typedef struct {
1840     int         nDatumEPSGCode;
1841     int         nMapInfoDatumID;
1842     const char  *pszOGCDatumName;
1843     int         nEllipsoid;
1844     double      dfShiftX;
1845     double      dfShiftY;
1846     double      dfShiftZ;
1847     double      dfDatumParm0; /* RotX */
1848     double      dfDatumParm1; /* RotY */
1849     double      dfDatumParm2; /* RotZ */
1850     double      dfDatumParm3; /* Scale Factor */
1851     double      dfDatumParm4; /* Prime Meridian */
1852 } MapInfoDatumInfo;
1853 
1854 typedef struct
1855 {
1856     int         nMapInfoId;
1857     const char *pszMapinfoName;
1858     double      dfA; /* semi major axis in meters */
1859     double      dfInvFlattening; /* Inverse flattening */
1860 } MapInfoSpheroidInfo;
1861 
1862 /*---------------------------------------------------------------------
1863  * The following are used for coordsys bounds lookup
1864  *--------------------------------------------------------------------*/
1865 
1866 bool    MITABLookupCoordSysBounds(TABProjInfo *psCS,
1867                                   double &dXMin, double &dYMin,
1868                                   double &dXMax, double &dYMax,
1869                                   bool bOnlyUserTable = false);
1870 int     MITABLoadCoordSysTable(const char *pszFname);
1871 void    MITABFreeCoordSysTable();
1872 bool    MITABCoordSysTableLoaded();  // TODO(schwehr): Unused?
1873 
1874 #endif /* MITAB_H_INCLUDED_ */
1875