Tabs LDEF/Tabs LDEF.c

/*
    File:       Tabs LDEF.c
 
    Contains:   LDEF that supports tabbed text
 
    Written by: Chris White 
 
    Copyright:  Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/10/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#include <Types.h>
#include <Lists.h>
#include <LowMem.h>
 
//#define   USE_LDEF
 
 
 
#ifndef USE_LDEF
pascal void tabsLDEF ( short theMessage, Boolean bSelect, Rect* theRect, Cell theCell,
                        short theOffset, short theLen, ListRef theList );
#endif
 
 
void DrawCell ( short theMessage, Boolean bSelect, Rect* cellRect, Cell theCell,
                    ListRef theHandle, short (*tabsOffset)[] );
void HiliteRect ( Rect* rect );
void AdjustStringWidth ( StringPtr theString, int availableWidth );
 
 
 
 
#define kStdIndent      2
 
 
 
#ifndef USE_LDEF
 
pascal void tabsLDEF ( short theMessage, Boolean bSelect, Rect* theRect, Cell theCell,
                        short theOffset, short theLen, ListRef theList )
                   
#else
 
pascal void main ( short theMessage, Boolean bSelect, Rect* theRect, Cell theCell,
                   short theOffset, short theLen, ListRef theList )
                   
#endif
 
{
    #pragma unused (theOffset,theLen)
    short (*tabsOffset)[];
    
    switch ( theMessage )
    {
        case lDrawMsg:
            // First, we need to grab hold of the tab positions
            tabsOffset = (short (*)[]) (*theList)->refCon;
            DrawCell (  theMessage, bSelect, theRect, theCell, theList, tabsOffset );
        break;
        
        case lHiliteMsg:
            HiliteRect ( theRect );
        break;
    }
    
    return;
}
 
 
 
void DrawCell ( short theMessage, Boolean bSelect, Rect* cellRect, Cell theCell,
                    ListRef theList, short (*tabsOffset)[] )
{
    #pragma unused(theMessage)
    SInt16      theLen;
    int         lastTabOffset = (*tabsOffset)[1];
    int         theIndex = 1;
    int         i, j;
    int         availableWidth;
    FontInfo    fontInfo;
    Str255      theString, theBit;
    
    
    // Erase the cell area first
    EraseRect ( cellRect );
    
    // Get current font information
    GetFontInfo ( &fontInfo );
    
    // Lock down the cell data
    HLock ( (*theList)->cells );
    
    // Get the cell text
    theLen = 255;
    LGetCell ( &theString[1], &theLen, theCell, theList );
    theString[0] = theLen;
    
    // Check for '\t' and draw the strings
    for ( i = 1, j = 1; i <= theString[0] + 1; i++, j++ )
    {
        // Assumes no '\t' on end, so also test for the last column
        if ( theString[i] == '\t' || i == theString[0] + 1 )
        {
            // Move to the correct location, taking into account the
            // font information. DrawString draws on the font base line.
            MoveTo ( kStdIndent + cellRect->left + (*tabsOffset)[theIndex++],
                        cellRect->top + fontInfo.ascent + fontInfo.leading - 1 );
            theBit[0] = i - lastTabOffset - 1;
            
            // If this is the last column, calculate the available width using
            // the list's view rect. Otherwise, we use the next tab position.
            if ( i == theString[0] + 1 )
                availableWidth = (*theList)->rView.right - (*theList)->rView.left
                                                         - (*tabsOffset)[theIndex - 1];
            else
                availableWidth = (*tabsOffset)[theIndex] - (*tabsOffset)[theIndex - 1];
            AdjustStringWidth ( theBit, availableWidth );
            DrawString ( theBit );
            lastTabOffset = i;
            j = 0;          // Should be 1, but about to be incremented
        }
        else
            theBit[j] = theString[i];
    }
    
    //  Hiliting - first one or when scrolling
    if ( bSelect )
        HiliteRect ( cellRect );
    
    // Unlock the cell data
    HUnlock ( (*theList)->cells );
    
    return;
}
 
 
 
void HiliteRect ( Rect* rect )
{
    // Setup the hilite mode for color
    LMSetHiliteMode ( LMGetHiliteMode ( ) & ~(1 << hiliteBit) );
    // Invert the cell rectangle
    InvertRect ( rect );
    
    return;
}
 
 
 
void AdjustStringWidth ( StringPtr theString, int availableWidth )
{
    int currentWidth;
    
    
    // Since we don't want the text to draw right up to
    // the column edge, we include a little extra space.
    availableWidth -= CharWidth ( ' ' );
    
    currentWidth = StringWidth ( theString );
    while ( currentWidth > availableWidth && theString[0] )
    {
        // We could use CharWidth ( 'É' ) and take that away from currentWidth.
        // However, the width of a text segment may be different from the sum
        // of its individual char widths, so this approach may be more acurate. 
        theString[--theString[0]] = 'É';
        currentWidth = StringWidth ( theString );
    }
    
    return;
}