Example #1
0
void SumatraUIAutomationTextRange::SetToDocumentRange()
{
    startPage = 1;
    startGlyph = 0;
    endPage = document->GetDM()->PageCount();
    endGlyph = GetPageGlyphCount(endPage);
}
Example #2
0
SumatraUIAutomationTextRange::SumatraUIAutomationTextRange(SumatraUIAutomationDocumentProvider* document, int pageNum)
    : refCount(1), document(document) {
    document->AddRef();

    startPage = pageNum;
    startGlyph = 0;
    endPage = pageNum;
    endGlyph = GetPageGlyphCount(pageNum);
}
Example #3
0
HRESULT STDMETHODCALLTYPE SumatraUIAutomationTextRange::ExpandToEnclosingUnit(enum TextUnit textUnit)
{
    //if document is closed, don't do anything
    if (!document->IsDocumentLoaded())
        return E_FAIL;

    //if not set, don't do anything
    if (IsNullRange())
        return S_OK;

    if (textUnit == TextUnit_Character)  {
        //done
        return S_OK;
    } else if (textUnit == TextUnit_Format) {
        // what is a "format" anyway?
        return S_OK;
    } else if (textUnit == TextUnit_Word) {
        // select current word at start endpoint
        int word_beg = FindPreviousWordEndpoint(startPage, startGlyph);
        int word_end = FindNextWordEndpoint(startPage, startGlyph);

        endPage = startPage;

        startGlyph = word_beg;
        endGlyph = word_end;

        return S_OK;
    } else if (textUnit == TextUnit_Line || textUnit == TextUnit_Paragraph) {
        // select current line or current paragraph. In general case these cannot be differentiated? Right?
        int word_beg = FindPreviousLineEndpoint(startPage, startGlyph);
        int word_end = FindNextLineEndpoint(startPage, startGlyph);

        endPage = startPage;

        startGlyph = word_beg;
        endGlyph = word_end;

        return S_OK;
    } else if (textUnit == TextUnit_Page) {
        // select current page

        // start from the beginning of start page
        startGlyph = 0;

        // to the end of the end page
        endGlyph = GetPageGlyphCount(endPage);

        return S_OK;
    } else if (textUnit == TextUnit_Document) {
        SetToDocumentRange();
        return S_OK;
    } else {
        return E_INVALIDARG;
    }
}
Example #4
0
HRESULT STDMETHODCALLTYPE SumatraUIAutomationTextRange::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count, int *moved)
{
    if (moved == NULL)
        return E_POINTER;

    // if document is closed, don't do anything
    if (!document->IsDocumentLoaded())
        return E_FAIL;

    // if not set, don't do anything
    if (IsNullRange())
        return S_OK;

    // what to move
    int *target_page, *target_glyph;
    if (endpoint == TextPatternRangeEndpoint_Start) {
        target_page = &startPage;
        target_glyph = &startGlyph;
    } else if (endpoint == TextPatternRangeEndpoint_End) {
        target_page = &endPage;
        target_glyph = &endGlyph;
    } else {
        return E_INVALIDARG;
    }

    class EndPointMover {
    protected:
        SumatraUIAutomationTextRange* target;
        int* target_page;
        int* target_glyph;

    public:
        // return false when cannot be moved
        virtual bool NextEndpoint() const {
            // HACK: Declaring these as pure virtual causes "unreferenced local variable" warnings ==> define a dummy body to get rid of warnings
            CrashIf(true);
            return false;
        }
        virtual bool PrevEndpoint() const {
            CrashIf(true);
            return false;
        }

        // return false when not appliable
        bool NextPage() const {
            int max_glyph = target->GetPageGlyphCount(*target_page);

            if (*target_glyph == max_glyph) {
                if (*target_page == target->GetPageCount()) {
                    // last page
                    return false;
                }

                // go to next page
                (*target_page)++;
                (*target_glyph) = 0;
            }
            return true;
        }
        bool PreviousPage() const {
            if (*target_glyph == 0) {
                if (*target_page == 1) {
                    // first page
                    return false;
                }

                // go to next page
                (*target_page)--;
                (*target_glyph) = target->GetPageGlyphCount(*target_page);
            }
            return true;
        }

        // do the moving
        int Move(int count, SumatraUIAutomationTextRange* target, int* target_page, int* target_glyph) {
            this->target = target;
            this->target_page = target_page;
            this->target_glyph = target_glyph;

            int retVal = 0;
            if (count > 0) {
                for (int i=0;i<count && (NextPage() || NextEndpoint());++i)
                    ++retVal;
            } else {
                for (int i=0;i<-count && (PreviousPage() || PrevEndpoint());++i)
                    ++retVal;
            }

            return retVal;
        }
    };
    class CharEndPointMover : public EndPointMover {
        bool NextEndpoint() const  {
            (*target_glyph)++;
            return true;
        }
        bool PrevEndpoint() const  {
            (*target_glyph)--;
            return true;
        }
    };
    class WordEndPointMover : public EndPointMover {
        bool NextEndpoint() const  {
            (*target_glyph) = target->FindNextWordEndpoint(*target_page, *target_glyph, true);
            return true;
        }
        bool PrevEndpoint() const  {
            (*target_glyph) = target->FindPreviousWordEndpoint(*target_page, *target_glyph, true);
            (*target_glyph)--;
            return true;
        }
    };
    class LineEndPointMover : public EndPointMover {
        bool NextEndpoint() const  {
            (*target_glyph) = target->FindNextLineEndpoint(*target_page, *target_glyph, true);
            return true;
        }
        bool PrevEndpoint() const  {
            (*target_glyph) = target->FindPreviousLineEndpoint(*target_page, *target_glyph, true);
            (*target_glyph)--;
            return true;
        }
    };

    // how much to move
    if (unit == TextUnit_Character) {
        CharEndPointMover mover;
        *moved = mover.Move(count, this, target_page, target_glyph);
    } else if (unit == TextUnit_Word || unit == TextUnit_Format) {
        WordEndPointMover mover;
        *moved = mover.Move(count, this, target_page, target_glyph);
    } else if (unit == TextUnit_Line || unit == TextUnit_Paragraph) {
        LineEndPointMover mover;
        *moved = mover.Move(count, this, target_page, target_glyph);
    } else if (unit == TextUnit_Page) {
        *moved = 0;
        *target_glyph = 0;

        if (count > 0) {
            // GetPageCount()+1 => allow overflow momentarily
            for (int i=0;i<count && *target_page!=GetPageCount()+1;++i) {
                (*target_page)++;
                (*moved)++;
            }

            // fix overflow, allow seeking to the end this way
            if (*target_page == GetPageCount()+1) {
                *target_page = GetPageCount();
                *target_glyph = GetPageGlyphCount(*target_page);
            }
        } else {
            for (int i=0;i<-count && *target_page!=1;++i) {
                (*target_page)--;
                (*moved)++;
            }
        }
    } else if (unit == TextUnit_Document) {
        if (count > 0) {
            int end_page = GetPageCount();
            int end_glyph = GetPageGlyphCount(*target_page);

            if (*target_page != end_page || *target_glyph != end_glyph) {
                *target_page = end_page;
                *target_glyph = end_glyph;
                *moved = 1;
            } else {
                *moved = 0;
            }
        } else {
            const int beg_page = 0;
            const int beg_glyph = 0;

            if (*target_page != beg_page || *target_glyph != beg_glyph) {
                *target_page = beg_page;
                *target_glyph = beg_glyph;
                *moved = 1;
            } else {
                *moved = 0;
            }
        }
    } else {
        return E_INVALIDARG;
    }

    // keep range valid
    if (endpoint == TextPatternRangeEndpoint_Start) {
        // drag end with start
        ValidateEndEndpoint();
    } else if (endpoint == TextPatternRangeEndpoint_End) {
        // drag start with end
        ValidateStartEndpoint();
    }

    return S_OK;
}