palm-os-sdk/PalmOne/Samples/VersaMailAttchmntPlugin/Src/VMPluginCW9.c

998 lines
22 KiB
C

/*
* VMPluginCW9.c
*
* main file for VMPluginCW9
*
* This is a test program that shows how to write a sample plugin
* for versamail. This Plugin helps you view text files. It handles
* four launch codes, which are used by versamail to launch this
* app.
*
* Copyright (c) 1999-2000 Palm, Inc. or its subsidiaries.
* All rights reserved.
*/
#include <PalmOS.h>
#include <PalmOSGlue.h>
#include "VMPluginCW9_Res.h"
#include "PalmVMPlugin.h"
/*********************************************************************
* Entry Points
*********************************************************************/
/*********************************************************************
* Global variables
*********************************************************************/
/*********************************************************************
* Internal Constants
*********************************************************************/
#define appError appErrorClass+1
/*********************************************************************
* Function Prototypes
*********************************************************************/
/* Plugin utility functions */
static Err PrvHandleGetInfo(void* cmdPBP);
static Err PrvHandleQuery(void* cmdPBP);
static Err PrvHandleSend(void* cmdPBP);
static Err PrvHandleReceive(void* cmdPBP);
/* UI related functions for text viewer */
static void ViewScroll(Word fieldID,Word scrollID,Short linesToScroll);
static void ViewUpdateScrollBar (Word fieldID,Word scrollID);
static void ViewPageScroll (Word fieldID,Word scrollID, WinDirectionType direction);
static Boolean ViewFormHandleEvent(void);
static MemPtr GetObjectPtr (UInt16 objectID);
/*********************************************************************
* FUNCTION: PilotMain
*
* DESCRIPTION: This is the main entry point for the application.
*
* PARAMETERS:
*
* cmd
* word value specifying the launch code.
*
* cmdPB
* pointer to a structure that is associated with the launch code
*
* launchFlags
* word value providing extra information about the launch.
*
* RETURNED:
* Result of launch, errNone if all went OK
*/
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
Err err = sysErrParamErr; /* If it gets a unknown launch code */
FrmAlert (VMTextPluginAlert);
switch (cmd)
{
case MMPRO_PLUGIN_GET_INFO_LAUNCHCODE:
// We need to return the info requested by VersaMail
err = PrvHandleGetInfo(cmdPBP);
break;
case MMPRO_PLUGIN_QUERY_LAUNCHCODE:
// We need to return a list of memo Items
err = PrvHandleQuery(cmdPBP);
break;
case MMPRO_PLUGIN_SEND_LAUNCHCODE :
// We need to return the item selected
err = PrvHandleSend(cmdPBP);
break;
case MMPRO_PLUGIN_RECEIVE_LAUNCHCODE:
// We need to show the text attachment passed to us
err = PrvHandleReceive(cmdPBP);
break;
case MMPRO_PLUGIN_EXTENDED_QUERY_LAUNCHCODE:
// Not supported by this Plugin.
break;
default:
break;
}
return err;
}
#if 0
#pragma mark -
#endif
/*********************************************************************
* FUNCTION: PrvHandleGetInfo
*
* DESCRIPTION: Handles MMPRO_PLUGIN_GET_INFO_LAUNCHCODE
*
*
* PARAMETERS:
*
* cmdPB
* pointer to a structure that is associated MMPRO_PLUGIN_GET_INFO_LAUNCHCODE
*
*
* RETURNED: None
*
*/
static Err PrvHandleGetInfo(void* cmdPBP)
{
pluginGetInfoParams *params; /* GetInfo parameters */
Int16 size;
MemHandle namesPH = NULL, nameslistH = NULL;
MemHandle extPH = NULL, extlistH = NULL;
MemHandle mimePH = NULL, mimelistH = NULL;
MemHandle rcvExtPH = NULL, rcvExtlistH = NULL;
MemHandle rcvMimePH = NULL, rcvMimeListH = NULL;
params = (pluginGetInfoParams *)cmdPBP;
// Our plugin supports sending and viewing so set it to true
params->supportsReceiving = true;
params->supportsSending = true;
// Version number has to be same as Versamail version number else
// Plugin will not work.
//
params->version = 0x26000;
// If sendInfo is requested from the plugin
if( params->getInfo == plugin_sendInfo || params->getInfo == plugin_allInfo)
{
params->numSendTypes = 1; // We support only .txt type //
// Copy the type the plugin supports
namesPH = MemHandleNew( sizeof(char*) * 1) ;
if(!namesPH)
goto Done;
params->listSendNames =(char **)MemHandleLock( namesPH );
size = ATTYPE_MAX_NAME_LEN;
nameslistH = MemHandleNew(size);
if(!nameslistH)
goto Done;
params->listSendNames[0] =(char *)MemHandleLock(nameslistH);
// This is what appears on the drop down list,to
MemSet(params->listSendNames[0], size, 0);
StrNCopy(params->listSendNames[0], "Text(.txt)", ATTYPE_MAX_NAME_LEN);
// Copy the File extension the plugin supports
extPH = MemHandleNew( sizeof(char*) * 1) ;
if(!extPH)
goto Done;
params->listSendFileExt =(char **)MemHandleLock(extPH);
size = StrLen("txt") + 1;
extlistH = MemHandleNew(size);
if(!extlistH)
goto Done;
params->listSendFileExt[0] =(char *)MemHandleLock(extlistH);
MemSet(params->listSendFileExt[0], size, 0);
StrCopy(params->listSendFileExt[0], "txt");
// Copy the MIME type the plugin supports
mimePH = MemHandleNew( sizeof(char*) * 1) ;
if(!mimePH)
goto Done;
params->listSendMIMEtypes =(char **)MemHandleLock(mimePH);
size = StrLen("text/plain") + 1;
mimelistH = MemHandleNew(size);
if(!mimelistH)
goto Done;
params->listSendMIMEtypes[0] =(char *)MemHandleLock(mimelistH);
MemSet(params->listSendMIMEtypes[0], size, 0);
StrCopy(params->listSendMIMEtypes[0], "text/plain");
}
// If receiveInfo is requested from the plugin
if( params->getInfo == plugin_receiveInfo || params->getInfo == plugin_allInfo)
{
params->numReceiveTypes = 1; // We support only .txt type
// Copy the File extension the plugin supports
rcvExtPH = MemHandleNew( sizeof(char*) * 1) ;
if(!rcvExtPH)
goto Done;
params->listReceiveFileExt =(char **)MemHandleLock(rcvExtPH);
size = StrLen("txt") + 1;
rcvExtlistH = MemHandleNew(size);
if(!rcvExtlistH)
goto Done;
params->listReceiveFileExt[0] =(char *)MemHandleLock(rcvExtlistH);
MemSet(params->listReceiveFileExt[0], size, 0);
StrCopy(params->listReceiveFileExt[0], "txt");
// Copy the MIME type the plugin supports
rcvMimePH = MemHandleNew( sizeof(char*) * 1) ;
if(!rcvMimePH)
goto Done;
params->listReceiveMIMEtypes =(char **)MemHandleLock(rcvMimePH);
size = StrLen("text/plain") + 1;
rcvMimeListH = MemHandleNew(size);
if(!rcvMimeListH)
goto Done;
params->listReceiveMIMEtypes[0] =(char *)MemHandleLock(rcvMimeListH);
MemSet(params->listReceiveMIMEtypes[0], size, 0);
StrCopy(params->listReceiveMIMEtypes[0], "text/plain");
}
return errNone;
Done:
/* If it comes here then there is an error */
/* Make sure we've freed everything you have allocated, and return a non
* zero error code to the plugin manager.
*/
if(mimePH)
{
MemHandleUnlock(mimePH);
MemHandleFree(mimePH);
}
if(extlistH)
{
MemHandleUnlock(extlistH);
MemHandleFree(extlistH);
}
if(extPH)
{
MemHandleUnlock(extPH);
MemHandleFree(extPH);
}
if(nameslistH)
{
MemHandleUnlock(nameslistH);
MemHandleFree(nameslistH);
}
if(namesPH)
{
MemHandleUnlock(namesPH);
MemHandleFree(namesPH);
}
if(rcvExtPH)
{
MemHandleUnlock(rcvExtPH);
MemHandleFree(rcvExtPH);
}
if(rcvExtlistH)
{
MemHandleUnlock(rcvExtlistH);
MemHandleFree(rcvExtlistH);
}
if(rcvMimePH)
{
MemHandleUnlock(rcvMimePH);
MemHandleFree(rcvMimePH);
}
return appError; // returning a non zero value
}
/*********************************************************************
* FUNCTION: PrvHandleQuery
*
* DESCRIPTION: Handles MMPRO_PLUGIN_QUERY_LAUNCHCODE
* We need to return a list of attachment here
*
* PARAMETERS:
*
* cmdPB
* pointer to a structure that is associated MMPRO_PLUGIN_QUERY_LAUNCHCODE
*
*
* RETURNED: None
*
*/
static Err PrvHandleQuery(void* cmdPBP)
{
pluginQueryParams* param=(pluginQueryParams*)cmdPBP;
DmOpenRef dbRef;
UInt16 numRecords = 0;
MemHandle listItemH = NULL, itemDesH = NULL, itemSizeH = NULL;
FormPtr originalForm = NULL, frm = NULL;
Boolean outOfMem = false;
int index;
UInt32 freeP, freeMax;
// Open MemoDB
dbRef = DmOpenDatabaseByTypeCreator('DATA', sysFileCMemo, dmModeReadWrite);
if(!dbRef)
goto Done;
// Get the total records in it
numRecords = DmNumRecords( dbRef );
// Allocate memory for listItems
if (NULL == (listItemH = MemHandleNew(numRecords * sizeof(char*))))
goto Done;
param->listItems =(char **)MemHandleLock(listItemH);
// Allocate memory for ItemDescriptors
if (NULL == (itemDesH = MemHandleNew(numRecords * sizeof(void*))))
goto Exit;
param->itemDescriptors = (void **)MemHandleLock( itemDesH );
// Allocate Memory for itemSizes
if (NULL == (itemSizeH = MemHandleNew(numRecords * sizeof(UInt32))))
goto Exit;
param->itemSizes =(UInt32 *)MemHandleLock(itemSizeH);
// If too much data needs to be processed, display the a wait form
if (numRecords > 100)
{
// hold the original form
originalForm = FrmGetActiveForm();
// initialize our form and field info
frm = FrmInitForm (PleasewaitForm);
FrmSetActiveForm (frm);
FrmDrawForm (frm);
}
// For each record populate the params to pass back to VersaMail
for (index = 0; index < numRecords && !outOfMem; index++)
{
MemHandle recHandle,tempHandle;
Char* recText;
int len;
UInt32 uniqueID;
// Get the Record
recHandle = DmQueryRecord ( dbRef , index);
if (!recHandle)
continue;
recText=(char *)MemHandleLock(recHandle);
len = StrLen(recText);
if (len>28)
len=28;
if (StrChr(recText,'\n'))
{
if (len > StrChr(recText,'\n')-recText )
len = StrChr(recText,'\n')-recText;
}
// Check for Free Memory on dynamic heap
MemHeapFreeBytes(0, &freeP, &freeMax);
if( freeP < 1000 ) // less than a K
{
outOfMem = true;
}
else
{
//Load listems value
tempHandle = MemHandleNew(len+1);
param->listItems[param->numItems]=(char *)MemHandleLock(tempHandle);
MemSet(param->listItems[param->numItems],len+1,0);
StrNCopy(param->listItems[param->numItems],recText,len);
*(param->listItems[param->numItems]+len) = '\0'; //--- Null terminate
// Load itemDescriptor
tempHandle = MemHandleNew(sizeof(UInt32));
param->itemDescriptors[param->numItems] =(char *)MemHandleLock(tempHandle);
DmRecordInfo(dbRef, index, 0L, &uniqueID, 0L);
*((UInt32 *)(param->itemDescriptors[param->numItems])) = uniqueID;
//Load itemSize
param->itemSizes[param->numItems] = MemHandleSize(recHandle);
param->numItems++;
}
MemHandleUnlock(recHandle);
DmReleaseRecord ( dbRef, index, false);
}
// Remove our Wait form and restore original form
if (numRecords > 100 )
{
FrmSetFocus (frm, noFocus);
FrmEraseForm (frm);
FrmDeleteForm (frm);
if (originalForm)
FrmSetActiveForm (originalForm);
}
DmCloseDatabase( dbRef );
return errNone;
// If we are here there has been an Error
Exit:
if(listItemH)
{
MemHandleUnlock(listItemH);
MemHandleFree(listItemH);
}
if(itemDesH)
{
MemHandleUnlock(itemDesH);
MemHandleFree(itemDesH);
}
Done:
DmCloseDatabase( dbRef );
return appError;
}
/*********************************************************************
* FUNCTION: PrvHandleSend
*
* DESCRIPTION: Handles MMPRO_PLUGIN_SEND_LAUNCHCODE
*
* PARAMETERS:
*
* cmdPB
* pointer to a structure that is associated MMPRO_PLUGIN_SEND_LAUNCHCODE
*
*
* RETURNED: None
*
*/
static Err PrvHandleSend(void* cmdPBP)
{
pluginSendParams* param=(pluginSendParams*)cmdPBP;
DmOpenRef dbRef;
UInt16 numRecords = 0;
UInt16 index;
MemHandle recHandle = NULL, itemNameH = NULL, mimeTypeH = NULL, fileExtH = NULL, handle;
Char* recText;
FormPtr originalForm = NULL;
FormPtr frm = NULL;
// Open MemoDB
dbRef = DmOpenDatabaseByTypeCreator('DATA', sysFileCMemo, dmModeReadWrite);
if(!dbRef)
goto Done;
// Get the total records in it
numRecords = DmNumRecords( dbRef );
// If too much data needs to be processed, display the a wait form
if (numRecords > 100)
{
// hold the original form
originalForm = FrmGetActiveForm();
// initialize our form and field info
frm = FrmInitForm (PleasewaitForm);
FrmSetActiveForm (frm);
FrmDrawForm (frm);
}
// param->selectedDescriptor contains a pointer to a UInt32 containing the uniqueID of the rec.
DmFindRecordByID(dbRef, *((UInt32 *)(param->selectedDescriptor)), &index);
// Get the Record
recHandle = DmQueryRecord ( dbRef , index);
recText=(char *)MemHandleLock(recHandle);
itemNameH = MemHandleNew(StrLen(param->item)+1 + StrLen(".txt") );
if(!itemNameH)
goto Done;
param->name =(char *)MemHandleLock(itemNameH);
// this is what the attachment is called
StrCopy(param->name,param->item);
StrCat(param->name,".txt");
// MIME and Extension
mimeTypeH = MemHandleNew(StrLen("text/plain")+1) ;
if(!mimeTypeH)
goto Exit;
param->MIMEtype = (Char*)MemHandleLock(mimeTypeH);
MemSet(param->MIMEtype, StrLen("text/plain")+1, 0);
fileExtH = MemHandleNew(StrLen("txt")+1) ;
if(!fileExtH)
goto Exit;
param->fileExt = (Char*)MemHandleLock(fileExtH);
MemSet(param->fileExt,StrLen("txt")+1, 0);
StrCopy(param->MIMEtype,"text/plain");
StrCopy(param->fileExt, "txt");
// allocate some memory, lock it down, and copy
// the memo pad item into it
// (this gets passed back to the caller)
handle = DmNewHandle(param->db,StrLen(recText)+1);
param->ptr =(char *)MemHandleLock(handle);
DmStrCopy(param->ptr,0,recText);
// return the size of the item we are passing back
param->size = StrLen(recText)+1;
MemHandleUnlock(recHandle);
DmReleaseRecord ( dbRef, index, false);
// Remove our Wait form and restore original form
if (numRecords > 100)
{
FrmSetFocus (frm, noFocus);
FrmEraseForm (frm);
FrmDeleteForm (frm);
if (originalForm)
FrmSetActiveForm (originalForm);
}
DmCloseDatabase( dbRef );
return errNone;
// If it comes here there has been an error
Exit:
if(itemNameH)
{
MemHandleUnlock(itemNameH);
MemHandleFree(itemNameH);
}
if(mimeTypeH)
{
MemHandleUnlock(mimeTypeH);
MemHandleFree(mimeTypeH);
}
Done:
DmCloseDatabase( dbRef );
return appError;
}
/*********************************************************************
* FUNCTION: PrvHandleReceive
*
* DESCRIPTION: Handles MMPRO_PLUGIN_RECEIVE_LAUNCHCODE
* Display the attachment
*
* PARAMETERS:
*
* cmdPB
* pointer to a structure that is associated MMPRO_PLUGIN_RECEIVE_LAUNCHCODE
*
*
* RETURNED: None
*
*/
static Err PrvHandleReceive(void* cmdPBP)
{
pluginParams *params = (pluginParams*)cmdPBP;
FormPtr originalForm;
FormPtr frm;
UInt16 strlen = 0;
MemHandle bodyHandle;
CharPtr bodyPtr=0;
int fldIndex=0;
if (!params)
{
return appError; // Return some non zero error
}
// hold the original form
originalForm = FrmGetActiveForm();
// initialize our form and field info
frm = FrmInitForm (ViewForm);
FrmSetActiveForm (frm);
fldIndex = FrmGetObjectIndex(frm, ViewBodyField);
// The purpose of the following section is to remove \r characters
// probably because we get \r\n and we only need \n
// Not that we can't write beyond the end of the params->data size
// otherwise DmWrite gets a fatal error.
if (params->data != NULL)
{
char *pNextStart = params->data;
char *pWriteHere = params->data;
int i = 0, nWriteLen = 0;
for (i = 0; i < params->size; i++)
{
if (!params->data[i])
break; // Stop as soon as a null is encountered
if (params->data[i] == '\r')
{
// Don't do this write if we're still at the beginning
nWriteLen = params->data + i - pNextStart;
if ((nWriteLen > 0) && (pNextStart != params->data))
DmWrite(params->data, (pWriteHere - params->data), pNextStart, nWriteLen);
pWriteHere += nWriteLen;
pNextStart = params->data + i + 1;
}
}
// Write the end part -
nWriteLen = params->data + params->size - pNextStart;
if (pNextStart != params->data && (nWriteLen > 0))
DmWrite(params->data, (pWriteHere - params->data), pNextStart, nWriteLen);
pWriteHere += nWriteLen;
// See if we can add a terminating null here
if (pWriteHere - params->data < params->size)
DmSet(params->data, (pWriteHere - params->data), 1, 0);
}
// this step was added so that we can determine whether the string was shortened
// by the removal of \r
if (params->data != NULL)
strlen = StrLen(params->data);
if (strlen > params->size)
strlen = params->size; // Limit this
if( strlen >= 62000 ) // Limit to this, including terminating null
strlen = 61999;
bodyHandle = DmNewHandle(params->db, strlen + 1) ;
if( !bodyHandle )
goto Done;
bodyPtr =(char *)MemHandleLock(bodyHandle);
if (strlen > 0)
DmWrite(bodyPtr, 0, params->data, strlen);
DmSet(bodyPtr, strlen, 1, 0);
MemHandleUnlock(bodyHandle);
FldSetTextHandle((FieldType *)FrmGetObjectPtr(frm, fldIndex), bodyHandle); // field owns the handle
ViewUpdateScrollBar(ViewBodyField,ViewScrollbarScrollBar);
FrmDrawForm (frm);
FldDrawField((FieldPtr)FrmGetObjectPtr(frm,fldIndex));
// handle user input
ViewFormHandleEvent();
// clean things up
FrmSetFocus (frm, noFocus);
FldSetTextHandle((FieldType *)FrmGetObjectPtr(frm, fldIndex), 0); // field owns the handle
FrmEraseForm (frm);
FrmDeleteForm (frm);
MemHandleFree(bodyHandle);
if (originalForm)
FrmSetActiveForm (originalForm);
return errNone;
Done:
return appError;
}
#if 0
#pragma mark -
#endif
/*********************************************************************
* FUNCTION: GetObjectPtr
*
* DESCRIPTION: Returns a pointer to an object
*
* PARAMETERS:
*
* objectID
* The ID of an object in a form
*
*
* RETURNED: None
*
*/
static MemPtr GetObjectPtr (UInt16 objectID)
{
FormType * form = FrmGetActiveForm();
return (FrmGetObjectPtr(form, FrmGetObjectIndex(form,objectID)));
}
/*********************************************************************
* FUNCTION: ViewUpdateScrollBar
*
* DESCRIPTION: Updates the scroll bar
*
* PARAMETERS:
*
* fieldID
* The ID of the field
* scrollID
* The ID of the scroll bar
*
*
* RETURNED: None
*
*/
static void ViewUpdateScrollBar (Word fieldID,Word scrollID)
{
Word scrollPos;
Word textHeight;
Word fieldHeight;
Short maxValue;
FieldPtr fld=(FieldPtr)GetObjectPtr(fieldID);
ScrollBarPtr bar=GetObjectPtr(scrollID);
// Get the values necessary to update the scroll bar.
FldGetScrollValues (fld, &scrollPos, &textHeight, &fieldHeight);
if (textHeight > fieldHeight)
maxValue = textHeight - fieldHeight;
else if (scrollPos)
maxValue = scrollPos;
else
maxValue = 0;
SclSetScrollBar(bar, scrollPos, 0, maxValue, fieldHeight-1);
}
/*********************************************************************
* FUNCTION: ViewScroll
*
* DESCRIPTION: Scrolls frm by a no. of lines
*
* PARAMETERS:
*
* fieldID
* The ID of the field
* scrollID
* The ID of the scroll bar
* linesToScroll
* Number of lines to scroll
*
*
* RETURNED: None
*
*/
static void ViewScroll(Word fieldID,Word scrollID,Short linesToScroll)
{
Word blankLines;
Short min;
Short max;
Short value;
Short pageSize;
FieldPtr fld=(FieldPtr)GetObjectPtr(fieldID);
ScrollBarPtr bar;
if (linesToScroll < 0)
{
blankLines = FldGetNumberOfBlankLines (fld);
FldScrollField (fld, -linesToScroll, winUp);
// If there were blank lines visible at the end of the field
// then we need to update the scroll bar.
if (blankLines)
{
// Update the scroll bar.
bar = GetObjectPtr(scrollID);
SclGetScrollBar (bar, &value, &min, &max, &pageSize);
if (blankLines > -linesToScroll)
max += linesToScroll;
else
max -= blankLines;
SclSetScrollBar (bar, value, min, max, pageSize);
}
}
else if (linesToScroll > 0)
FldScrollField (fld, linesToScroll, winDown);
}
/*********************************************************************
* FUNCTION: ViewPageScroll
*
* DESCRIPTION: Scrolls a page
*
* PARAMETERS:
*
* fieldID
* The ID of the field
* scrollID
* The ID of the scroll bar
* direction
* up or down
*
*
* RETURNED: None
*
*/
static void ViewPageScroll (Word fieldID,Word scrollID, WinDirectionType direction)
{
Short value;
Short min;
Short max;
Short pageSize;
Word linesToScroll;
FieldPtr fld;
ScrollBarPtr bar;
fld = (FieldPtr)GetObjectPtr(fieldID);
if (FldScrollable (fld, direction))
{
linesToScroll = FldGetVisibleLines (fld) - 1;
FldScrollField (fld, linesToScroll, direction);
// Update the scroll bar.
bar = GetObjectPtr(scrollID);
SclGetScrollBar (bar, &value, &min, &max, &pageSize);
if (direction == winUp)
value -= linesToScroll;
else
value += linesToScroll;
SclSetScrollBar (bar, value, min, max, pageSize);
}
FldGrabFocus (fld);
}
/*********************************************************************
* FUNCTION: ViewFormHandleEvent
*
* DESCRIPTION: Scrolls a page
*
* PARAMETERS:
*
* fieldID
* The ID of the field
* scrollID
* The ID of the scroll bar
* direction
* up or down
*
*
* RETURNED: None
*
*/
static Boolean ViewFormHandleEvent(void)
{
EventType event;
Boolean handled=false;
FormPtr frm=0;
while (true)
{
handled = false;
EvtGetEvent (&event, evtWaitForever);
if (SysHandleEvent (&event))
continue;
if (event.eType == ctlSelectEvent)
{
if ( event.data.ctlEnter.controlID==ViewDoneButton)
{
return true;
}
}
else if (event.eType == fldChangedEvent)
{
ViewUpdateScrollBar (ViewBodyField,ViewScrollbarScrollBar);
}
else if (event.eType == appStopEvent)
{
EvtAddEventToQueue(&event);
return false;
}
else if (event.eType == keyDownEvent)
{
if (event.data.keyDown.chr == pageUpChr)
{
ViewPageScroll (ViewBodyField,ViewScrollbarScrollBar, winUp);
handled = true;
}
else if (event.data.keyDown.chr == pageDownChr)
{
ViewPageScroll (ViewBodyField,ViewScrollbarScrollBar, winDown);
handled = true;
}
else
{
// An ordinary ASCII character was entered. Have the form
// give the field the character. Then check to see if the
// scrolling changed.
frm = FrmGetActiveForm ();
FrmHandleEvent (frm, &event);
ViewUpdateScrollBar (ViewBodyField,ViewScrollbarScrollBar);
handled=true;
}
}
else if (event.eType == sclRepeatEvent)
{
ViewScroll (ViewBodyField,ViewScrollbarScrollBar ,event.data.sclRepeat.newValue - event.data.sclRepeat.value);
}
// Check if the form can handle the event
if (!handled)
FrmHandleEvent (FrmGetActiveForm(), &event);
}
}