slackbuilds/office/Ted/docSectProperties.c

1106 lines
27 KiB
C

/************************************************************************/
/* */
/* Manipulate iten properties in a document. */
/* */
/************************************************************************/
# include "docBaseConfig.h"
# include <stdlib.h>
# include <appDebugon.h>
# include <utilPropMask.h>
# include "docPropVal.h"
# include "docSectProperties.h"
# define MIN_COL_WIDE ( 20* 36 )
# define MIN_GAP_WIDE ( 20* 12 )
# define DEF_GAP_WIDE ( 20* 36 )
/************************************************************************/
/* */
/* Translate section property numbers to notes property numbers. */
/* */
/************************************************************************/
const int DOCsectNOTE_PROP_MAP[FEPprop_COUNT]=
{
SPpropFOOTNOTE_STARTNR,
SPpropFOOTNOTE_JUSTIFICATION,
-1, /* No SPpropFOOTNOTE_PLACEMENT, */
SPpropFOOTNOTE_RESTART,
SPpropFOOTNOTE_STYLE,
SPpropENDNOTE_STARTNR,
-1, /* No SPpropENDNOTE_JUSTIFICATION, */
-1, /* No SPpropENDNOTE_PLACEMENT, */
SPpropENDNOTE_RESTART,
SPpropENDNOTE_STYLE,
};
const int * const DOCsectFOOTNOTE_PROP_MAP= DOCsectNOTE_PROP_MAP;
const int * const DOCsectENDNOTE_PROP_MAP= DOCsectNOTE_PROP_MAP+ NOTESprop_COUNT;
static const int DocSectIntProps[]=
{
DGpropPAGE_WIDTH,
DGpropPAGE_HEIGHT,
DGpropLEFT_MARGIN,
DGpropRIGHT_MARGIN,
DGpropTOP_MARGIN,
DGpropBOTTOM_MARGIN,
DGpropHEADER_POSITION,
DGpropFOOTER_POSITION,
DGpropGUTTER,
DGpropMARGMIR,
SPpropSTYLE,
SPpropTITLEPG,
SPpropBREAK_KIND,
SPpropNUMBER_STYLE,
SPpropNUMBER_HYPHEN,
SPpropPAGE_RESTART,
SPpropSTART_PAGE,
SPpropCOLUMN_COUNT,
SPpropCOLUMN_SPACING,
SPpropLINEBETCOL,
SPpropFOOTNOTE_STARTNR,
SPpropFOOTNOTE_JUSTIFICATION,
/* No SPpropFOOTNOTE_PLACEMENT, */
SPpropFOOTNOTE_RESTART,
SPpropFOOTNOTE_STYLE,
SPpropENDNOTE_STARTNR,
/* No SPpropENDNOTE_JUSTIFICATION, */
/* No SPpropENDNOTE_PLACEMENT, */
SPpropENDNOTE_RESTART,
SPpropENDNOTE_STYLE,
};
static const int DocSectIntPropCount= sizeof(DocSectIntProps)/sizeof(int);
/************************************************************************/
/* */
/* Fill a mask with notes properties that are relevant for a section. */
/* I.E: Set those section properties that are a note property. */
/* */
/************************************************************************/
void docFillSectNotesMask( PropertyMask * spMask )
{
int i;
for ( i= 0; i < FEPprop_COUNT; i++ )
{
if ( DOCsectNOTE_PROP_MAP[i] >= 0 )
{ PROPmaskADD( spMask, DOCsectNOTE_PROP_MAP[i] ); }
}
}
/************************************************************************/
/* */
/* Make sure all column width are zero, or that none of them is. */
/* */
/************************************************************************/
static void docSectCheckFixedColumnWidth( SectionProperties * sp )
{
if ( sp->spColumnCount > 1 )
{
int haveZero= 0;
int haveWidth= 0;
int col;
SectionColumn * sc;
sc= sp->spColumns;
for ( col= 0; col < sp->spColumnCount; sc++, col++ )
{
if ( sc->scColumnWidthTwips == 0 )
{ haveZero++; }
else{ haveWidth++; }
}
if ( haveZero && haveWidth )
{
sc= sp->spColumns;
for ( col= 0; col < sp->spColumnCount; sc++, col++ )
{ sc->scColumnWidthTwips= 0; }
}
}
return;
}
/************************************************************************/
/* */
/* Change section properties and tell what has been changed. */
/* */
/************************************************************************/
int docUpdSectProperties( PropertyMask * pSpDoneMask,
SectionProperties * spTo,
const PropertyMask * spSetMask,
const SectionProperties * spSet )
{
PropertyMask doneMask;
int p;
utilPropMaskClear( &doneMask );
for ( p= 0; p < DocSectIntPropCount; p++ )
{
int prop= DocSectIntProps[p];
int oval;
int nval;
if ( ! PROPmaskISSET( spSetMask, prop ) )
{ continue; }
oval= docGetSectionProperty( spTo, prop );
nval= docGetSectionProperty( spSet, prop );
if ( oval == nval )
{ continue; }
if ( docSetSectionProperty( spTo, prop, nval ) )
{ LLDEB(prop,nval); return -1; }
PROPmaskADD( &doneMask, prop );
}
if ( PROPmaskISSET( spSetMask, SPpropCOLUMN_COUNT ) )
{
if ( spTo->spColumnCount != spSet->spColumnCount )
{
if ( docSectionPropertiesSetColumnCount( spTo,
spSet->spColumnCount ) )
{ LDEB(spSet->spColumnCount); return -1; }
PROPmaskADD( &doneMask, SPpropCOLUMN_COUNT );
}
}
if ( PROPmaskISSET( spSetMask, SPpropCOLUMNS ) )
{
int count;
if ( spTo->spColumnCount < spSet->spColumnCount )
{ count= spTo->spColumnCount; }
else{ count= spSet->spColumnCount; }
if ( count > 1 )
{
const SectionColumn * scFrom= spSet->spColumns;
SectionColumn * scTo= spTo->spColumns;
int col;
for ( col= 0; col < count- 1; scTo++, scFrom++, col++ )
{
if ( scTo->scColumnWidthTwips != scFrom->scColumnWidthTwips )
{
scTo->scColumnWidthTwips= scFrom->scColumnWidthTwips;
PROPmaskADD( &doneMask, SPpropCOLUMNS );
}
if ( scTo->scSpaceToRightTwips != scFrom->scSpaceToRightTwips )
{
scTo->scSpaceToRightTwips= scFrom->scSpaceToRightTwips;
PROPmaskADD( &doneMask, SPpropCOLUMNS );
}
}
if ( scTo->scColumnWidthTwips != scFrom->scColumnWidthTwips )
{
scTo->scColumnWidthTwips= scFrom->scColumnWidthTwips;
PROPmaskADD( &doneMask, SPpropCOLUMNS );
}
}
}
docSectCheckFixedColumnWidth( spTo );
if ( pSpDoneMask )
{ *pSpDoneMask= doneMask; }
return 0;
}
void docSectPropertyDifference( PropertyMask * pDiffMask,
const SectionProperties * sp1,
const PropertyMask * cmpMask,
const SectionProperties * sp2 )
{
PropertyMask diffMask;
int p;
utilPropMaskClear( &diffMask );
for ( p= 0; p < DocSectIntPropCount; p++ )
{
int prop= DocSectIntProps[p];
int oval;
int nval;
if ( ! PROPmaskISSET( cmpMask, prop ) )
{ continue; }
oval= docGetSectionProperty( sp1, prop );
nval= docGetSectionProperty( sp2, prop );
if ( oval == nval )
{ continue; }
PROPmaskADD( &diffMask, prop );
}
if ( PROPmaskISSET( cmpMask, SPpropCOLUMNS ) )
{
int count;
if ( sp1->spColumnCount < sp2->spColumnCount )
{ count= sp1->spColumnCount; }
else{ count= sp2->spColumnCount; }
if ( count > 1 )
{
const SectionColumn * sc1= sp1->spColumns;
const SectionColumn * sc2= sp2->spColumns;
int col;
for ( col= 0; col < count- 1; sc1++, sc2++, col++ )
{
if ( sc1->scColumnWidthTwips != sc2->scColumnWidthTwips )
{ PROPmaskADD( &diffMask, SPpropCOLUMNS ); }
if ( sc1->scSpaceToRightTwips != sc2->scSpaceToRightTwips )
{ PROPmaskADD( &diffMask, SPpropCOLUMNS ); }
}
if ( sc1->scColumnWidthTwips != sc2->scColumnWidthTwips )
{ PROPmaskADD( &diffMask, SPpropCOLUMNS ); }
}
}
*pDiffMask= diffMask;
return;
}
/************************************************************************/
/* */
/* Clean, Initialize section properties. */
/* */
/************************************************************************/
void docCleanSectionProperties( SectionProperties * sp )
{
if ( sp->spColumns )
{ free( sp->spColumns ); }
return;
}
void docInitSectionProperties( SectionProperties * sp )
{
utilInitDocumentGeometry( &(sp->spDocumentGeometry) );
sp->spStyle= 0;
sp->spColumnSpacingTwips= DEF_GAP_WIDE;
sp->spLineBetweenColumns= 0;
sp->spHasTitlePage= 0;
sp->spBreakKind= DOCibkPAGE;
sp->spPageNumberStyle= DOCpgnDEC;
sp->spPageNumberHyphen= DOCpgnhPGNHNSH;
sp->spRestartPageNumbers= 0;
sp->spColumnCount= 1;
sp->spColumns= (SectionColumn *)0;
sp->spStartPageNumber= 0;
docInitFootEndNotesProperties( &(sp->spNotesProperties) );
return;
}
int docSectionPropertiesSetColumnCount( SectionProperties * sp,
int n )
{
if ( n > 1 && sp->spColumnCount < n )
{
SectionColumn * sc= (SectionColumn *)realloc( sp->spColumns,
n* sizeof(SectionColumn) );
if ( ! sc )
{ LXDEB(n,sc); return -1; }
sp->spColumns= sc;
if ( sp->spColumnCount == 1 )
{
sc->scSpaceToRightTwips= 0;
sc->scColumnWidthTwips= 0;
}
sc= sp->spColumns+ sp->spColumnCount;
while( sp->spColumnCount < n )
{
sc->scSpaceToRightTwips= 0;
sc->scColumnWidthTwips= 0;
sc++; sp->spColumnCount++;
}
}
sp->spColumnCount= n;
return 0;
}
/************************************************************************/
/* */
/* Copy SectionProperties. */
/* */
/* NOTE that the headers and footers are not copied. */
/* */
/************************************************************************/
int docCopySectionProperties( SectionProperties * to,
const SectionProperties * from )
{
int i;
if ( docSectionPropertiesSetColumnCount( to, from->spColumnCount ) )
{ LDEB(from->spColumnCount); return -1; }
to->spDocumentGeometry= from->spDocumentGeometry;
to->spStyle= from->spStyle;
to->spColumnSpacingTwips= from->spColumnSpacingTwips;
to->spLineBetweenColumns= from->spLineBetweenColumns;
to->spHasTitlePage= from->spHasTitlePage;
to->spBreakKind= from->spBreakKind;
to->spPageNumberStyle= from->spPageNumberStyle;
to->spPageNumberHyphen= from->spPageNumberHyphen;
to->spRestartPageNumbers= from->spRestartPageNumbers;
to->spStartPageNumber= from->spStartPageNumber;
/* docSectionPropertiesSetColumnCount() has allocated the memory */
if ( from->spColumnCount > 1 )
{
for ( i= 0; i < from->spColumnCount; i++ )
{ to->spColumns[i]= from->spColumns[i]; }
}
to->spNotesProperties= from->spNotesProperties;
docSectCheckFixedColumnWidth( to );
return 0;
}
int docSectSetEqualColumnWidth( SectionProperties * sp )
{
int col;
SectionColumn * sc;
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
int pageWide;
int colWide;
pageWide= dg->dgPageWideTwips-
dg->dgLeftMarginTwips- dg->dgRightMarginTwips;
if ( sp->spColumnCount < 2 )
{ return pageWide; }
colWide= ( pageWide- ( sp->spColumnCount- 1 )*
sp->spColumnSpacingTwips )/ sp->spColumnCount;
sc= sp->spColumns;
for ( col= 0; col < sp->spColumnCount; sc++, col++ )
{
sc->scColumnWidthTwips= 0;
sc->scSpaceToRightTwips= 0;
}
return colWide;
}
int docSectSetExplicitColumnWidth( SectionProperties * sp )
{
int col;
SectionColumn * sc;
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
int pageWide;
int colWide;
pageWide= dg->dgPageWideTwips-
dg->dgLeftMarginTwips- dg->dgRightMarginTwips;
if ( sp->spColumnCount < 2 )
{ LDEB(sp->spColumnCount); return -1; }
colWide= ( pageWide- ( sp->spColumnCount- 1 )*
sp->spColumnSpacingTwips )/ sp->spColumnCount;
if ( colWide < MIN_COL_WIDE )
{ LLDEB(colWide,MIN_COL_WIDE); return -1; }
sc= sp->spColumns;
for ( col= 0; col < sp->spColumnCount; sc++, col++ )
{
sc->scColumnWidthTwips= colWide;
sc->scSpaceToRightTwips= sp->spColumnSpacingTwips;
}
return 0;
}
/************************************************************************/
/* */
/* Determine the column margins. */
/* */
/* Because of gutters and/or mirrored margins, the page geometry is */
/* not necessarily identical to that in the section properties. */
/* */
/************************************************************************/
void docSectGetColumnX( int * pXLine,
int * pX0,
int * pX1,
const SectionProperties * sp,
const DocumentGeometry * dgPage,
int column )
{
int x0= dgPage->dgLeftMarginTwips;
int col;
if ( sp->spColumnCount < 2 )
{
*pX0= dgPage->dgLeftMarginTwips;
*pX1= dgPage->dgPageWideTwips- dgPage->dgRightMarginTwips;
return;
}
for ( col= 0; col < column; col++ )
{
if ( sp->spColumns[col].scColumnWidthTwips == 0 )
{ break; }
x0 += sp->spColumns[col].scColumnWidthTwips;
x0 += sp->spColumns[col].scSpaceToRightTwips;
}
if ( col < column || sp->spColumns[column].scColumnWidthTwips == 0 )
{
int pageWide;
int colWide;
pageWide= dgPage->dgPageWideTwips-
dgPage->dgLeftMarginTwips- dgPage->dgRightMarginTwips;
colWide= ( pageWide- ( sp->spColumnCount- 1 )*
sp->spColumnSpacingTwips )/ sp->spColumnCount;
x0= dgPage->dgLeftMarginTwips+
column* ( colWide+ sp->spColumnSpacingTwips );
*pXLine= x0- sp->spColumnSpacingTwips/ 2;
*pX0= x0;
*pX1= x0+ colWide;
}
else{
if ( column == 0 )
{
*pXLine= x0- sp->spColumnSpacingTwips/ 2;
}
else{
*pXLine= x0- sp->spColumns[column-1].scSpaceToRightTwips/ 2;
}
*pX0= x0;
*pX1= x0+ sp->spColumns[column].scColumnWidthTwips;
}
return;
}
/************************************************************************/
/* */
/* Set a section property. */
/* */
/************************************************************************/
int docSetSectionProperty( SectionProperties * sp,
int prop,
int arg )
{
DocumentGeometry * dg= &(sp->spDocumentGeometry);
switch( prop )
{
case DGpropPAGE_WIDTH:
dg->dgPageWideTwips= arg;
break;
case DGpropPAGE_HEIGHT:
dg->dgPageHighTwips= arg;
break;
case DGpropLEFT_MARGIN:
dg->dgLeftMarginTwips= arg;
break;
case DGpropRIGHT_MARGIN:
dg->dgRightMarginTwips= arg;
break;
case DGpropTOP_MARGIN:
dg->dgTopMarginTwips= arg;
break;
case DGpropBOTTOM_MARGIN:
dg->dgBottomMarginTwips= arg;
break;
case DGpropHEADER_POSITION:
if ( arg != 0 )
{ dg->dgHeaderPositionTwips= arg; }
break;
case DGpropFOOTER_POSITION:
if ( arg != 0 )
{ dg->dgFooterPositionTwips= arg; }
break;
case DGpropGUTTER:
dg->dgGutterTwips= arg;
break;
case DGpropMARGMIR:
dg->dgMirrorMargins= arg != 0;
break;
case SPpropSTYLE:
sp->spStyle= arg;
break;
case SPpropTITLEPG:
sp->spHasTitlePage= ( arg != 0 );
break;
case SPpropBREAK_KIND:
sp->spBreakKind= arg;
break;
case SPpropNUMBER_STYLE:
sp->spPageNumberStyle= arg;
break;
case SPpropNUMBER_HYPHEN:
sp->spPageNumberHyphen= arg;
break;
case SPpropPAGE_RESTART:
sp->spRestartPageNumbers= arg;
break;
case SPpropSTART_PAGE:
sp->spStartPageNumber= arg;
break;
case SPpropCOLUMN_COUNT:
if ( docSectionPropertiesSetColumnCount( sp, arg ) )
{ LDEB(arg); return -1; }
break;
case SPpropCOLUMN_SPACING:
sp->spColumnSpacingTwips= arg;
break;
case SPpropLINEBETCOL:
sp->spLineBetweenColumns= ( arg != 0 );
break;
/* FOOTNOTE */
case SPpropFOOTNOTE_STARTNR:
docSetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropSTARTNR, arg );
return 0;
case SPpropFOOTNOTE_JUSTIFICATION:
docSetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropJUSTIFICATION, arg );
return 0;
/* No
case SPpropFOOTNOTE_PLACEMENT:
docSetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropPLACEMENT, arg );
return 0;
*/
case SPpropFOOTNOTE_RESTART:
docSetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropRESTART, arg );
return 0;
case SPpropFOOTNOTE_STYLE:
docSetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropSTYLE, arg );
return 0;
/* ENDNOTE */
case SPpropENDNOTE_STARTNR:
docSetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropSTARTNR, arg );
return 0;
/* No
case SPpropENDNOTE_JUSTIFICATION:
docSetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropJUSTIFICATION, arg );
return 0;
*/
/* No
case SPpropENDNOTE_PLACEMENT:
docSetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropPLACEMENT, arg );
return 0;
*/
case SPpropENDNOTE_RESTART:
docSetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropRESTART, arg );
return 0;
case SPpropENDNOTE_STYLE:
docSetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropSTYLE, arg );
return 0;
default:
LLDEB(prop,arg); return -1;
}
return 0;
}
/************************************************************************/
/* */
/* Get a section property. */
/* */
/************************************************************************/
int docGetSectionProperty( const SectionProperties * sp,
int prop )
{
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
switch( prop )
{
case DGpropPAGE_WIDTH:
return dg->dgPageWideTwips;
case DGpropPAGE_HEIGHT:
return dg->dgPageHighTwips;
case DGpropLEFT_MARGIN:
return dg->dgLeftMarginTwips;
case DGpropRIGHT_MARGIN:
return dg->dgRightMarginTwips;
case DGpropTOP_MARGIN:
return dg->dgTopMarginTwips;
case DGpropBOTTOM_MARGIN:
return dg->dgBottomMarginTwips;
case DGpropHEADER_POSITION:
return dg->dgHeaderPositionTwips;
case DGpropFOOTER_POSITION:
return dg->dgFooterPositionTwips;
case DGpropGUTTER:
return dg->dgGutterTwips;
case DGpropMARGMIR:
return dg->dgMirrorMargins;
case SPpropSTYLE:
return sp->spStyle;
case SPpropTITLEPG:
return sp->spHasTitlePage;
case SPpropBREAK_KIND:
return sp->spBreakKind;
case SPpropNUMBER_STYLE:
return sp->spPageNumberStyle;
case SPpropNUMBER_HYPHEN:
return sp->spPageNumberHyphen;
case SPpropPAGE_RESTART:
return sp->spRestartPageNumbers;
case SPpropSTART_PAGE:
return sp->spStartPageNumber;
case SPpropCOLUMN_COUNT:
return sp->spColumnCount;
case SPpropCOLUMN_SPACING:
return sp->spColumnSpacingTwips;
break;
case SPpropLINEBETCOL:
return sp->spLineBetweenColumns;
break;
/* FOOTNOTE */
case SPpropFOOTNOTE_STARTNR:
return docGetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropSTARTNR );
return 0;
case SPpropFOOTNOTE_JUSTIFICATION:
return docGetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropJUSTIFICATION );
return 0;
/* No
case SPpropFOOTNOTE_PLACEMENT:
return docGetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropPLACEMENT );
return 0;
*/
case SPpropFOOTNOTE_RESTART:
return docGetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropRESTART );
return 0;
case SPpropFOOTNOTE_STYLE:
return docGetNotesProperty( &(sp->spNotesProperties.fepFootnotesProps),
NOTESpropSTYLE );
return 0;
/* ENDNOTE */
case SPpropENDNOTE_STARTNR:
return docGetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropSTARTNR );
return 0;
/* No
case SPpropENDNOTE_JUSTIFICATION:
return docGetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropJUSTIFICATION );
return 0;
*/
/* No
case SPpropENDNOTE_PLACEMENT:
return docGetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropPLACEMENT );
return 0;
*/
case SPpropENDNOTE_RESTART:
return docGetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropRESTART );
return 0;
case SPpropENDNOTE_STYLE:
return docGetNotesProperty( &(sp->spNotesProperties.fepEndnotesProps),
NOTESpropSTYLE );
return 0;
default:
LDEB(prop); return -1;
}
return 0;
}
/************************************************************************/
/* */
/* Return the sum of the other widths in a section with explicit */
/* column layout. Additionally, assign a victim whose column width can */
/* be narrowed to allocate extra space. */
/* */
/* The maximum value is the value that leaves MIN_COL_WIDE as the */
/* column width of the victim. */
/* */
/************************************************************************/
static int docSectColsSumOthers( int * pVictim,
int * pMaxValue,
const SectionProperties * sp,
int col,
int colOther )
{
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
int pageWide;
int sumOthers= 0;
int i;
int victim;
int left;
pageWide= dg->dgPageWideTwips-
dg->dgLeftMarginTwips- dg->dgRightMarginTwips;
for ( i= 0; i < sp->spColumnCount- 1; i++ )
{
if ( i == col )
{ continue; }
sumOthers += sp->spColumns[i].scColumnWidthTwips;
sumOthers += sp->spColumns[i].scSpaceToRightTwips;
}
if ( i != col )
{ sumOthers += sp->spColumns[i].scColumnWidthTwips; }
sumOthers += colOther;
if ( col == sp->spColumnCount- 1 )
{ victim= sp->spColumnCount-2; }
else{ victim= sp->spColumnCount-1; }
left= sp->spColumns[victim].scColumnWidthTwips- MIN_COL_WIDE;
if ( pVictim )
{ *pVictim= victim; }
if ( pMaxValue )
{ *pMaxValue= pageWide- sumOthers+ left; }
return sumOthers;
}
/************************************************************************/
/* */
/* Claim extra space by subtracting it from the column width of the */
/* victim. Applies for explicit column layout only. */
/* */
/************************************************************************/
static int docSectReserveWidth( SectionProperties * sp,
int victim,
int sumValues )
{
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
int pageWide;
pageWide= dg->dgPageWideTwips-
dg->dgLeftMarginTwips- dg->dgRightMarginTwips;
if ( sumValues > pageWide )
{
int narrowed;
narrowed= pageWide- sumValues+ sp->spColumns[victim].scColumnWidthTwips;
if ( narrowed < MIN_COL_WIDE )
{ LDEB(narrowed); return -1; }
sp->spColumns[victim].scColumnWidthTwips= narrowed;
}
return 0;
}
/************************************************************************/
static void docSectGetEqualWidths(
int * pColWide,
int * pGapWide,
int * pMaxColWide,
int * pMaxGapWide,
const SectionProperties * sp )
{
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
int pageWide;
int colWide;
int maxColWide;
int gapWide;
int maxGapWide;
int ncol= sp->spColumnCount;
int ngap= sp->spColumnCount- 1;
pageWide= dg->dgPageWideTwips-
dg->dgLeftMarginTwips- dg->dgRightMarginTwips;
colWide= ( pageWide- ngap* sp->spColumnSpacingTwips )/ ncol;
maxColWide= ( pageWide- ngap* MIN_GAP_WIDE )/ ncol;
gapWide= sp->spColumnSpacingTwips;
if ( ngap == 0 )
{ maxGapWide= 0; }
else{ maxGapWide= ( pageWide- ncol* MIN_COL_WIDE )/ ngap; }
if ( pColWide )
{ *pColWide= colWide; }
if ( pGapWide )
{ *pGapWide= gapWide; }
if ( pMaxColWide )
{ *pMaxColWide= maxColWide; }
if ( pMaxGapWide )
{ *pMaxGapWide= maxGapWide; }
return;
}
/************************************************************************/
/* */
/* Get the spacing right of a column. */
/* */
/************************************************************************/
int docSectGetColumnSpacing( int * pMinValue,
int * pMaxValue,
const SectionProperties * sp,
int col )
{
int value;
int maxValue;
int haveFixedWidth;
haveFixedWidth= docSectPropsFixedWidthColumns( sp );
if ( haveFixedWidth )
{ docSectGetEqualWidths( (int *)0, &value, (int *)0, &maxValue, sp ); }
else{
docSectColsSumOthers( (int *)0, &maxValue,
sp, col, sp->spColumns[col].scColumnWidthTwips );
value= sp->spColumns[col].scSpaceToRightTwips;
}
if ( pMaxValue )
{ *pMaxValue= maxValue; }
if ( pMinValue )
{ *pMinValue= MIN_GAP_WIDE; }
return value;
}
/************************************************************************/
/* */
/* Set the spacing right of a column. */
/* */
/************************************************************************/
int docSectSetColumnSpacing( SectionProperties * sp,
int col,
int newValue )
{
int maxValue;
int haveFixedWidth;
haveFixedWidth= docSectPropsFixedWidthColumns( sp );
if ( haveFixedWidth )
{
if ( col > 0 )
{ LLLDEB(haveFixedWidth,col,newValue); return -1; }
docSectGetEqualWidths( (int *)0, (int *)0, (int *)0, &maxValue, sp );
if ( newValue < MIN_GAP_WIDE || newValue > maxValue )
{ LLDEB(newValue,maxValue); return -1; }
sp->spColumnSpacingTwips= newValue;
}
else{
int victim;
int sumOthers;
sumOthers= docSectColsSumOthers( &victim, &maxValue,
sp, col, sp->spColumns[col].scColumnWidthTwips );
if ( newValue < MIN_GAP_WIDE || newValue > maxValue )
{ LLDEB(newValue,maxValue); return -1; }
if ( victim == col )
{ LLDEB(victim,col); return -1; }
if ( docSectReserveWidth( sp, victim, sumOthers+ newValue ) )
{ LLDEB(sumOthers,newValue); return -1; }
sp->spColumns[col].scSpaceToRightTwips= newValue;
}
return 0;
}
/************************************************************************/
/* */
/* Get the spacing right of a column. */
/* */
/************************************************************************/
int docSectGetColumnWidth( int * pMinValue,
int * pMaxValue,
const SectionProperties * sp,
int col )
{
int value;
int maxValue;
int haveFixedWidth;
haveFixedWidth= docSectPropsFixedWidthColumns( sp );
if ( haveFixedWidth )
{
docSectGetEqualWidths( &value, (int *)0, &maxValue, (int *)0, sp );
}
else{
docSectColsSumOthers( (int *)0, &maxValue,
sp, col, sp->spColumns[col].scSpaceToRightTwips );
value= sp->spColumns[col].scColumnWidthTwips;
}
if ( pMinValue )
{ *pMinValue= MIN_COL_WIDE; }
if ( pMaxValue )
{ *pMaxValue= maxValue; }
return value;
}
/************************************************************************/
/* */
/* Set the spacing right of a column. */
/* */
/************************************************************************/
int docSectSetColumnWidth( SectionProperties * sp,
int col,
int newValue )
{
int maxValue;
int haveFixedWidth;
haveFixedWidth= docSectPropsFixedWidthColumns( sp );
if ( haveFixedWidth )
{
const DocumentGeometry * dg= &(sp->spDocumentGeometry);
int pageWide;
int gapWide;
docSectGetEqualWidths( (int *)0, &gapWide, &maxValue, (int *)0, sp );
if ( newValue < MIN_COL_WIDE || newValue > maxValue )
{ LLDEB(newValue,maxValue); return -1; }
pageWide= dg->dgPageWideTwips-
dg->dgLeftMarginTwips- dg->dgRightMarginTwips;
gapWide= ( pageWide- ( sp->spColumnCount* newValue ) )/
( sp->spColumnCount- 1 );
if ( gapWide < MIN_GAP_WIDE )
{ LLDEB(gapWide,MIN_GAP_WIDE); gapWide= MIN_GAP_WIDE; }
sp->spColumnSpacingTwips= gapWide;
}
else{
int victim;
int sumOthers;
sumOthers= docSectColsSumOthers( &victim, &maxValue,
sp, col, sp->spColumns[col].scSpaceToRightTwips );
if ( newValue < MIN_COL_WIDE || newValue > maxValue )
{ LLDEB(newValue,maxValue); return -1; }
if ( victim == col )
{ LLDEB(victim,col); return -1; }
if ( docSectReserveWidth( sp, victim, sumOthers+ newValue ) )
{ LLDEB(sumOthers,newValue); return -1; }
sp->spColumns[col].scColumnWidthTwips= newValue;
}
return 0;
}