/**********
 * Copyright (c) 2003-2004 Greg Parker.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **********/

#include "includes.h"
#include "formutils.h"
#include "rsrc/rsrc.h"
#include "forms/CollapseUtils.h"

void *PrvGetObjectByID(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    return FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, id));
}

UInt16 PrvGetObjectIndexByID(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    return FrmGetObjectIndex(frmP, id);
}

Err PrvRemoveObjectByID(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    return FrmRemoveObject(&frmP, FrmGetObjectIndex(frmP, id));
}

void PrvShowObjectByID(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    FrmShowObject(frmP, FrmGetObjectIndex(frmP, id));
}

void PrvHideObjectByID(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    FrmHideObject(frmP, FrmGetObjectIndex(frmP, id));
}

void PrvGetObjectBoundsByID(UInt16 id, RectangleType *bounds)
{
    FormPtr frmP = FrmGetActiveForm();
    FrmGetObjectBounds(frmP, FrmGetObjectIndex(frmP, id), bounds);
}

void PrvSetObjectBoundsByID(UInt16 id, const RectangleType *bounds)
{
    FormPtr frmP = FrmGetActiveForm();
    FrmSetObjectBounds(frmP, FrmGetObjectIndex(frmP, id), bounds);
}

void PrvSetFocusByID(UInt16 id)
{
    FrmSetFocus(FrmGetActiveForm(), 
                PrvGetObjectIndexByID(id));
}

void PrvCopyFieldContents(UInt16 id, char *dst)
{
    FieldPtr fldP = (FieldPtr) PrvGetObjectByID(id);
    MemHandle h = FldGetTextHandle(fldP);
    if (h) {
        StrCopy(dst, MemHandleLock(h));
        MemHandleUnlock(h);
    } else {
        StrCopy(dst, "");
    }
}

Int16 PrvGetControlValue(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    return FrmGetControlValue(frmP, index);
}

void PrvSetControlValue(UInt16 id, Int16 value)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    FrmSetControlValue(frmP, index, value);
}

const char *PrvGetControlLabel(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    ControlType *ctl = FrmGetObjectPtr(frmP, index);
    return CtlGetLabel(ctl);
}

void PrvSetControlLabel(UInt16 id, const char *label)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    ControlType *ctl = FrmGetObjectPtr(frmP, index);
    CtlSetLabel(ctl, label);
}

void PrvSetControlEnabled(UInt16 id, Boolean usable)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    ControlType *ctl = FrmGetObjectPtr(frmP, index);
    CtlSetEnabled(ctl, usable);
}

Boolean PrvGetControlEnabled(UInt16 id)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    ControlType *ctl = FrmGetObjectPtr(frmP, index);
    return CtlEnabled(ctl);
}

void PrvSetControlGraphics(UInt16 id, UInt16 bitmapID, UInt16 selectedBitmapID)
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    ControlType *ctl = FrmGetObjectPtr(frmP, index);
    CtlSetGraphics(ctl, bitmapID, selectedBitmapID);
}

void PrvDrawControl(UInt16 id) 
{
    FormPtr frmP = FrmGetActiveForm();
    UInt16 index = FrmGetObjectIndex(frmP, id);
    ControlType *ctl = FrmGetObjectPtr(frmP, index);
    CtlDrawControl(ctl);
}


Err PrvStoreFieldToRecord(FieldPtr fld, void *recordP, UInt32 *offset)
{
    Err err = 0;
    char *str;

    FldReleaseFocus(fld);
    FldCompactText(fld);
    str = FldGetTextPtr(fld);
    if (str) {
        // store length byte, string, null char
        // length byte includes null char
        char len = 1+StrLen(str);
        err = DmSet(recordP, *offset, 1, len);
        if (!err) err = DmWrite(recordP, 1+*offset, str, len);
        if (!err) *offset += 1+len;
    } else {
        err = DmSet(recordP, *offset, 1, 0);
        if (!err) *offset += 1;
    }
    return err;
}


Boolean PrvSetFieldToValue(FieldPtr fld, char *str)
{
    MemHandle textH;

    // kill old field contents, if any
    textH = FldGetTextHandle(fld);
    FldSetTextHandle(fld, NULL);
    if (textH) MemHandleFree(textH);

    // make new handle for field contents
    textH = MemHandleNew(1+StrLen(str));
    if (!textH) return false;

    // set default value
    StrCopy(MemHandleLock(textH), str);
    MemHandleUnlock(textH);

    FldSetTextHandle(fld, textH);
    return true;
}

Boolean PrvSetFieldToValueByID(UInt16 id, char *str)
{
    return PrvSetFieldToValue(PrvGetObjectByID(id), str);
}

void PrvFieldSelectAll(UInt16 id) 
{
    FieldPtr field = PrvGetObjectByID(id);
    UInt16 end = FldGetTextLength(field);
    FldSetSelection(field, 0, end);
}

void PrvScrollField(UInt16 fldID, EventPtr e)
{
    Int16 delta = e->data.sclRepeat.newValue - e->data.sclRepeat.value;
    WinDirectionType dir;

    if (delta > 0) {
        dir = winDown;
    } else {
        delta = -delta;
        dir = winUp;
    }

    FldScrollField(PrvGetObjectByID(fldID), delta, dir);
    PrvUpdateScrollbarForField(fldID, e->data.sclRepeat.scrollBarID);
}


void PrvUpdateScrollbarForField(UInt16 fldID, UInt16 sclID)
{
    FieldPtr fldP = PrvGetObjectByID(fldID);
    ScrollBarPtr sclP = PrvGetObjectByID(sclID);
    Int16 scrollPos;
    Int16 textHeight;
    Int16 fieldHeight;
    Int16 maxValue;

    FldGetScrollValues(fldP, &scrollPos, &textHeight, &fieldHeight); 

    if (textHeight > fieldHeight) 
        maxValue = textHeight - fieldHeight;
    else if (scrollPos) 
        maxValue = scrollPos;
    else 
        maxValue = 0;

    SclSetScrollBar(sclP, scrollPos, 0, maxValue,fieldHeight-1); 
}


void NetworkError(char *msg, Err err)
{
    if (err != netErrUserCancel) {
        char errbuf[256];
        SysErrString(err, errbuf, sizeof(errbuf));
        errbuf[255] = '\0';
        FrmCustomAlert(NetworkErrorAlertID, msg, "", errbuf);
    }
}


// After screen size change, resize a table to an integer number 
// of rows, and resize a scrollbar to match it.
void PrvResizeTableAndScrollbar(FormPtr frmP, Int16 dh, Int16 dv, 
                                UInt16 tableIndex, UInt16 scrollbarIndex)
{
    TablePtr table;
    Coord rowHeight;
    RectangleType tblBounds, sclBounds;

    table = FrmGetObjectPtr(frmP, tableIndex);
    TblGetBounds(table, &tblBounds);
    rowHeight = TblGetRowHeight(table, 0);
    // fixme adjust to width too
    tblBounds.extent.y += dv;
    tblBounds.extent.y -= tblBounds.extent.y % rowHeight;
    TblSetBounds(table, &tblBounds);
    
    FrmGetObjectBounds(frmP, scrollbarIndex, &sclBounds);
    sclBounds.extent.y = tblBounds.extent.y;
    FrmSetObjectBounds(frmP, scrollbarIndex, &sclBounds);
}


void PrvResizeFieldAndScrollbar(FormPtr frmP, Int16 dh, Int16 dv, 
                                UInt16 fieldIndex, UInt16 scrollbarIndex) 
{
    FieldPtr field;
    Coord rowHeight;
    RectangleType fldBounds, sclBounds;

    field = FrmGetObjectPtr(frmP, fieldIndex);
    FrmGetObjectBounds(frmP, fieldIndex, &fldBounds);
    // fixme adjust to width too
    fldBounds.extent.y += dv;
    FrmSetObjectBounds(frmP, fieldIndex, &fldBounds);
    FldRecalculateField(field, false);
    
    FrmGetObjectBounds(frmP, scrollbarIndex, &sclBounds);
    sclBounds.extent.y = fldBounds.extent.y;
    FrmSetObjectBounds(frmP, scrollbarIndex, &sclBounds);
    PrvUpdateScrollbarForField(FrmGetObjectId(frmP, fieldIndex), 
                               FrmGetObjectId(frmP, scrollbarIndex));
}

void PrvHandleDisplayChange(FormPtr frmP, Boolean needsRedraw)
{
    if (needsRedraw  ||  CollapseCheckForPin10NeedToRedraw()) {
        if (CollapseGetAPIVersion() == sonyVersion1) FrmEraseForm(frmP);
        FrmDrawForm(frmP);
    }
}
