TumblerSource/Tumbler_teutilities.c

//
//
//      teutilities.c
//
//      Supplemental TextEdit utilities.
//      
//
//      Author:     Nick Thompson & Pablo Fernicola, with thanks to the QuickDraw 3D team
//      Date:       Monday, February 3, 1992
//
//      Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
//
//
 
#include <Script.h>
#include "Tumbler_prototypes.h"
 
#include "Tumbler_teutilities.h"
 
//
//  TEICut is an intelligent version of TECut. If the selection is a range
//  of words, TEICut cuts the selection and removes a space from either the
//  beginning or end of the selection point when the result of cutting leaves
//  one too many spaces in a sentence. The resulting change in size of the
//  TextEdit record is returned.
//
//  NOTE: This function does not work properly in all situations. It may still
//      need some work.
//
 
short TEICut(TEHandle theTE)
 
{   OffsetTable     startOffsets, endOffsets;
    short           selStart, selEnd, characters;
    Handle          theScrap;
 
    if (!(characters = (**theTE).selStart - (**theTE).selEnd))
        return(0);
 
    FindWord(*((**theTE).hText), (**theTE).teLength, (**theTE).selStart, true,
                    0L, startOffsets);
    FindWord(*((**theTE).hText), (**theTE).teLength, (**theTE).selEnd, false,
                    0L, endOffsets);
 
    if ((startOffsets[0].offFirst == (**theTE).selStart) &&
        (endOffsets[0].offSecond  == (**theTE).selEnd)) {
 
        //
        //  Both the beginning and end of the current selection is on
        //  word boundaries.
        
 
        selStart = (**theTE).selStart;
        selEnd = (**theTE).selEnd;
        if ((*((**theTE).hText))[selStart - 1] == ' ') {
            TESetSelect(selStart - 1, selEnd, theTE);
            TECut(theTE);
            theScrap = TEScrapHandle();
            BlockMove((char *) (*theScrap) + 1, (*theScrap), TEGetScrapLength() - 1);
            TESetScrapLength(TEGetScrapLength() - 1);
            ZeroScrap();
            TEToScrap();
            characters--;
        } else if ((*((**theTE).hText))[selEnd] == ' ') {
            TESetSelect(selStart, selEnd + 1, theTE);
            TECut(theTE);
            TESetScrapLength(TEGetScrapLength() - 1);
            ZeroScrap();
            TEToScrap();
            characters--;
        } else {
            TECut(theTE);
        }
    } else {
        TECut(theTE);
    }
    return(characters);
}
 
 
//
//  TEIPaste is an intelligent version of TEPaste. When pasting into a sentence,
//  an extra space may be added to either the start or end of the insertion
//  to maintain readibility of the resulting sentence. Optionally, pointers
//  may be provided to spaceBefore and/or spaceAfter. These flags return
//  true if a space was inserted before or after the insertion respectively.
//
//  NOTE: This function does not always work properly. It still needs work.
//
 
short TEIPaste(TEHandle theTE, short *spaceBefore, short *spaceAfter)
 
{   OffsetTable     startOffsets, endOffsets;
    short           addSpaceAfter, characters;
 
    characters = (**theTE).selStart - (**theTE).selEnd;
 
    if (spaceBefore)
        *spaceBefore = false;
    if (spaceAfter)
        *spaceAfter  = false;
 
    FindWord(*((**theTE).hText), (**theTE).teLength, (**theTE).selStart, false,
                    0L, startOffsets);
    FindWord(*((**theTE).hText), (**theTE).teLength, (**theTE).selEnd, true,
                    0L, endOffsets);
 
    addSpaceAfter = ((endOffsets[0].offFirst == (**theTE).selEnd) &&
                     ((*((**theTE).hText))[(**theTE).selEnd] != ' '));
 
    if ((startOffsets[0].offSecond == (**theTE).selStart) &&
            ((*((**theTE).hText))[(**theTE).selStart - 1] != ' ')) {
        TEKey(' ', theTE);
        characters++;
        if (spaceBefore)
            *spaceBefore = true;
    }
 
    TEPaste(theTE);
    characters += TEGetScrapLength();
 
    if (addSpaceAfter) {
        TEKey(' ', theTE);
        characters++;
        if (spaceAfter)
            *spaceAfter = true;
    }
    return(characters);
}
 
 
//
//  TEIsFrontOfLine, given an offset and a TextEdit handle, returns true if
//  the given offset is at the beginning of a line start.
//
 
short TEIsFrontOfLine(short offset, TEHandle theTE)
 
{   short       line = 0;
 
    if ((**theTE).teLength == 0)
        return(true);
 
    if (offset >= (**theTE).teLength)
        return( (*((**theTE).hText))[(**theTE).teLength - 1] == 0x0d );
 
    while ((**theTE).lineStarts[line] < offset)
        line++;
 
    return( (**theTE).lineStarts[line] == offset );
}
 
 
//
//  TEGetLine, given an offset and a TextEdit handle, returns the line number
//  of the line that contains the offset.
//
 
short TEGetLine(short offset, TEHandle theTE)
 
{   short       line = 0;
 
    if (offset > (**theTE).teLength)
        return((**theTE).nLines);
 
    while ((**theTE).lineStarts[line] < offset)
        line++;
    
    return(line);
}