예제 #1
0
파일: draw.c 프로젝트: docwhat/cwimp
/*
 * This function is based on the DrawIntro and DrawBlinds
 * functions in Vexed, a Cool GPL Palm Game by
 * "James McCombe" <*****@*****.**>
 * http://spacetube.tsx.org
 */
void
DrawIntro () {
  VoidHand Title_Handle;
  BitmapPtr Title;
  char text[40];
  SWord penx, peny;
  Boolean bstate;

  /* If a game is on, don't do the splash */
  if( stor.currplayer >= 0 ) return;

  // load bitmap resource and get handle
  Title_Handle = DmGet1Resource ('Tbmp', bmpTitle);
  // lock the bitmap resource into memory and get a pointer to it
  Title = MemHandleLock (Title_Handle);

  // draw the bitmap ( 160x160 )
  WinDrawBitmap (Title, 0, 0);

  /* Text Strings */
  StrPrintF (text, IntroVersionString, VERSION);
  WinDrawChars (text, StrLen (text), 5, 6);

  StrPrintF (text, IntroForPalmString, 153);
  WinDrawChars (text, StrLen (text), 52, 50);

  StrPrintF (text, IntroTapHereString, VERSION);
  WinDrawChars (text, StrLen (text), 45, 85);

  // unload the bitmap from memory (unlock)
  MemHandleUnlock (Title_Handle);

  // Loop till screen is tapped
  while (bstate)
    EvtGetPen (&penx, &peny, &bstate);
  while (!bstate)
    EvtGetPen (&penx, &peny, &bstate);

  /* If the user clicked in the drawing area, then
   * do a Draw Blinds and clear the PenQueue.
   */
  if( peny < 160 ) {
    // DrawBlinds
    int i, x;
    float delay;

    EvtFlushPenQueue();

    delay = .01 * SysTicksPerSecond();

    for (i = 0; i < 16; i++) {
      for (x = i; x < 160; x += 16) {
        WinEraseLine( 0,x, 159,x );
      }
      SysTaskDelay(delay);
    }
  } /* if( peny < 160 ) */

}
예제 #2
0
void fastPoll( void )
	{
	RANDOM_STATE randomState;
	BYTE buffer[ RANDOM_BUFSIZE + 8 ];
	WinHandle winHandle;
	Coord xCoord, yCoord;
	Boolean flag;
	uint64_t ticks;
	nsecs_t nsTime;

	initRandomData( randomState, buffer, RANDOM_BUFSIZE );

	/* Get the event-available and low-level event-available flag, current
	   pen status, and handle of the window with the input focus */
	flag = EvtEventAvail();
	addRandomValue( randomState, flag );
	flag = EvtSysEventAvail( TRUE );
	addRandomValue( randomState, flag );
	EvtGetPen( &xCoord, &yCoord, &flag );
	addRandomValue( randomState, xCoord );
	addRandomValue( randomState, yCoord );
	winHandle = EvtGetFocusWindow();
	addRandomValue( randomState, winHandle );

	/* Get the number of ticks of the (software) millisecond clock used
	   by the scheduler, and the length of time in nanoseconds since the
	   last reset */
	ticks = TimGetTicks();
	addRandomData( randomState, &ticks, sizeof( uint64_t ) );
	nsTime = SysGetRunTime();
	addRandomData( randomState, &nsTime, sizeof( nsecs_t ) );

	/* Get the value of the real-time and runtime clocks in nanoseconds.
	   One of these may just be a wrapper for SysGetRunTime(), in addition
	   it's likely that they're hardware-specific, being CPU-level cycle
	   counters of some kind */
	nsTime = system_real_time();
	addRandomData( randomState, &nsTime, sizeof( nsecs_t ) );
	nsTime = system_time();
	addRandomData( randomState, &nsTime, sizeof( nsecs_t ) );

	/* Flush any remaining data through */
	endRandomData( randomState, 5 );
	}
예제 #3
0
파일: exams.c 프로젝트: timn/unimatrix
Boolean
ExamsFormHandleEvent(EventPtr event)
{
  FormPtr frm=FrmGetActiveForm();
  Boolean handled = false;
  Boolean categoryEdited, reDraw=false;
  UInt16 category, numRecords;
  ControlType *ctl;
  UInt32 *recordList;

  if (event->eType == ctlSelectEvent) {
    // button handling
    switch (event->data.ctlSelect.controlID) {
      case BUTTON_ex_back:
        handled=true;
        FrmGotoForm(FORM_main);
        break;

      case BUTTON_ex_add:
        handled=true;
        if (CountCourses() > 0) {
          gExamsLastSelRowUID=0;
          FrmPopupForm(FORM_exam_details);
        } else {
          FrmAlert(ALERT_nocourses);
        }
        break;

      case BUTTON_ex_edit:
        handled=true;
        gExamsLastSelRowUID=TblGetRowData(GetObjectPtr(TABLE_exams), gExamsSelRow);
        FrmPopupForm(FORM_exam_details);
        break;

      case BUTTON_ex_note:
      {
        UInt16 index=0;

        handled=true;

        gExamsLastSelRowUID=TblGetRowData(GetObjectPtr(TABLE_exams), gExamsSelRow);
        DmFindRecordByID(DatabaseGetRefN(DB_MAIN), gExamsLastSelRowUID, &index);
        NoteSet(index, FORM_exams);
        FrmPopupForm(NewNoteView);
        break;
      }

      case BUTTON_ex_del:
        handled=true;
        gExamsLastSelRowUID=TblGetRowData(GetObjectPtr(TABLE_exams), gExamsSelRow);
        ExamDelete();
        break;

      case BUTTON_ex_beam:
        handled=true;
        gExamsLastSelRowUID=TblGetRowData(GetObjectPtr(TABLE_exams), gExamsSelRow);
        ExamBeam();
        break;

      case LIST_ex_cat_trigger:
        handled=true;
        category=DatabaseGetCat();
        numRecords=DmNumRecordsInCategory(DatabaseGetRef(), DELETE_CATEGORY);
        recordList=(UInt32 *)MemPtrNew(numRecords * sizeof(UInt32));
        CatPreEdit(numRecords, recordList);
        categoryEdited = CategorySelect(DatabaseGetRef(), frm,
                                        LIST_ex_cat_trigger, LIST_ex_cat, false,
                                        &category, gCategoryName, 0,
                                        STRING_cat_edit); // categoryDefaultEditCategoryString
        if (categoryEdited || (category != DatabaseGetCat())) {
          reDraw=true;
          DatabaseSetCat(category);
          ctl = GetObjectPtr(LIST_ex_cat_trigger);
          CategoryGetName(DatabaseGetRef(), category, gCategoryName); 
          CategorySetTriggerLabel(ctl, gCategoryName);
        }
        CatPostEdit(numRecords, recordList);
        if (reDraw) {
          gExamsOffset=0;
          gExamsSelRow=0;
          FrmUpdateForm(FORM_exams, frmRedrawUpdateCode);
        }
        if (recordList != NULL)  MemPtrFree((MemPtr)recordList);
        break;

      default:
        break;
    }
  } else if (event->eType == tblEnterEvent) {
    UInt16 i;
    
    if (event->data.tblEnter.column == EXCOL_DONE) {
      handled=false;
    } else if (event->data.tblEnter.column == EXCOL_NOTE) {
      MemHandle m;
      Boolean hasNote=false;

      gExamsSelRow=event->data.tblEnter.row;
      for (i=0; i < TblGetNumberOfRows(event->data.tblEnter.pTable); ++i) {
        RectangleType r;
        TblGetItemBounds(event->data.tblEnter.pTable, i, EXCOL_SELI, &r);
        TableDrawSelection(event->data.tblEnter.pTable, i, event->data.tblEnter.column, &r);
      }


      m = DmQueryRecord(DatabaseGetRefN(DB_MAIN), TblGetRowID(event->data.tblEnter.pTable, event->data.tblEnter.row));
      if (m) {
        ExamDBRecord *ex = (ExamDBRecord *)MemHandleLock(m);
        if (ex->note) hasNote = true;
        else          hasNote = false;
        MemHandleUnlock(m);
      }

      if (hasNote) {
        Coord newPointX, newPointY;
        Boolean isPenDown=false, drawn=false;
        RectangleType fieldBounds;
        IndexedColorType curForeColor, curBackColor, curTextColor;
        Char noteSymb[2] = { GADGET_NOTESYMBOL, 0 };
        FontID oldFont;
  
  
        EvtGetPen(&newPointX, &newPointY, &isPenDown);
        TblGetItemBounds(event->data.tblEnter.pTable, event->data.tblEnter.row, EXCOL_NOTE, &fieldBounds);
  
        oldFont = FntSetFont(symbolFont);
        while (isPenDown){
          if (! drawn && RctPtInRectangle(newPointX, newPointY, &fieldBounds)) {
            curForeColor = WinSetForeColor(UIColorGetTableEntryIndex(UIObjectSelectedForeground));
            curBackColor = WinSetBackColor(UIColorGetTableEntryIndex(UIObjectSelectedFill));
            curTextColor = WinSetTextColor(UIColorGetTableEntryIndex(UIObjectSelectedForeground));
            TNDrawCharsToFitWidth(noteSymb, &fieldBounds);
            WinSetForeColor(curForeColor);
            WinSetForeColor(curBackColor);
            WinSetForeColor(curTextColor);
            drawn = true;
          } else if (drawn && ! RctPtInRectangle(newPointX, newPointY, &fieldBounds)) {
            curForeColor = WinSetForeColor(UIColorGetTableEntryIndex(UIObjectForeground));
            curBackColor = WinSetBackColor(UIColorGetTableEntryIndex(UIObjectFill));
            curTextColor = WinSetTextColor(UIColorGetTableEntryIndex(UIObjectForeground));
            TNDrawCharsToFitWidth(noteSymb, &fieldBounds);
            WinSetForeColor(curForeColor);
            WinSetForeColor(curBackColor);
            WinSetForeColor(curTextColor);
            drawn = false;
          }
          EvtGetPen(&newPointX, &newPointY, &isPenDown);
        }
        FntSetFont(oldFont);
      } else {
        handled = true;
      }
    } else {
      gExamsSelRow=event->data.tblEnter.row;
      for (i=0; i < TblGetNumberOfRows(event->data.tblEnter.pTable); ++i) {
        RectangleType r;
        TblGetItemBounds(event->data.tblEnter.pTable, i, EXCOL_SELI, &r);
        TableDrawSelection(event->data.tblEnter.pTable, i, event->data.tblEnter.column, &r);
      }
      handled=true;
    }
  } else if (event->eType == tblSelectEvent) {
    if (event->data.tblEnter.column == EXCOL_DONE) {
      MemHandle mex;
      ExamDBRecord *ex;
      Boolean done=(TblGetItemInt(event->data.tblSelect.pTable, event->data.tblSelect.row, event->data.tblSelect.column) == 0) ? false : true;
      UInt16 flags, index=TblGetRowID(event->data.tblSelect.pTable, event->data.tblSelect.row);

      mex=DmGetRecord(DatabaseGetRefN(DB_MAIN), index);
      ex = MemHandleLock(mex);
      flags = ex->flags;

      if (done) {
        flags |= EX_FLAG_DONE;
      } else {
        flags &= (EX_FLAG_DONE ^ 0xFFFF);
      }

      DmWrite(ex, offsetof(ExamDBRecord, flags), &flags, sizeof(flags));
      DmReleaseRecord(DatabaseGetRefN(DB_MAIN), index, false);

      TblMarkRowInvalid(event->data.tblSelect.pTable, event->data.tblSelect.row);
      TblRedrawTable(event->data.tblSelect.pTable);

      MemHandleUnlock(mex);

    } else if (event->data.tblEnter.column == EXCOL_NOTE) {
      ControlType *ctl=GetObjectPtr(BUTTON_ex_note);
      // Don't need code twice, just read ctlSelect Event for BUTTON_ex_note
      CtlHitControl(ctl);
    }
    handled=true;
  } else if (event->eType == ctlRepeatEvent) {
    // Repeat buttons pressed
    if( event->data.ctlRepeat.controlID == REPEAT_ex_up )
      gExamsOffset -= 1;
    else
      gExamsOffset += 1;

    ExamsTableInit();
    TblMarkTableInvalid(GetObjectPtr(TABLE_exams));
    TblRedrawTable(GetObjectPtr(TABLE_exams));
  } else if (event->eType == keyDownEvent) {
    // We have a hard button assigned and it was pressed
    if (TxtCharIsHardKey(event->data.keyDown.modifiers, event->data.keyDown.chr)) {
      if (! (event->data.keyDown.modifiers & poweredOnKeyMask)) {
        FrmGotoForm(FORM_main);
        handled = true;
      }
    }
  } else if (event->eType == menuOpenEvent) {
    return HandleMenuOpenEvent(event);
  } else if (event->eType == menuEvent) {
    // forwarding of menu events
    return HandleMenuEvent(event->data.menu.itemID);
  } else if (event->eType == frmOpenEvent) {
    // initializes and draws the form
    ControlType *ctl;

    gExamsOffset=0;
    ExamsTableInit();
    FrmDrawForm (frm);

    ctl = GetObjectPtr(LIST_ex_cat_trigger);
    CategoryGetName (DatabaseGetRef(), DatabaseGetCat(), gCategoryName); 
    CategorySetTriggerLabel (ctl, gCategoryName); 

    handled = true;
  } else if (event->eType == frmUpdateEvent) {
    // redraws the form if needed
    gExamsOffset=0;
    ExamsTableInit();
    FrmDrawForm(frm);
    handled = false;
  } else if (event->eType == frmCloseEvent) {
    // this is done if form is closed
    // TblEraseTable(GetObjectPtr(TABLE_exams));
    // ExamsFormFree();
    FrmEraseForm(frm);
  }

  return (handled);

}
예제 #4
0
파일: xfer.c 프로젝트: jemyzhang/DiddleBug
/*
** TrackXferDone
*/
static void TrackXferDone(DynamicButtonType* btn) {
  RectangleType bounds[5], frame, popFrame, popShadowFrame;
  Boolean penDown, on_button;
  Int16 x, y, clicked_on = 0;
  Int16 state = 1;
  Int16 i = 0;
  WinHandle offscreenH = NULL;
  FormType* frm = FrmGetActiveForm();
  const UInt16 listIdx = FrmGetObjectIndex(frm, XferDoneList);
  ListType* list = FrmGetObjectPtr(frm, listIdx);
  UInt16 width = 0, choices = 0;
  Err err = errNone;
  Char str[48];
  Int16 n = 0;

  /* Save the old drawing context */
  WinPushDrawState();

  /* This should match the XferDoneButton bounds */
  FrmGetObjectBounds(frm, FrmGetObjectIndex(frm, btn->id), &bounds[0]);

  /* Invert the done button */
  SelectAndDrawButton(btn, true);
  SndPlaySystemSound(sndClick);

  /* Set the status of each menu pick */
  for (; i < 4; i++)
    d.xfer.status[i] = 0x00;
  
  if (xferGotoIsAlways)
    d.xfer.status[0] = TRACKXFERDONE_ALWAYS;
  else if (xferGotoIsNever)
    d.xfer.status[0] = TRACKXFERDONE_NEVER;
  else if (p.flags&PFLAGS_XFER_GOTO)
    d.xfer.status[0] = TRACKXFERDONE_CHECKED;

  if (xferCompleteIsAlways)
    d.xfer.status[1] = TRACKXFERDONE_ALWAYS;
  else if (xferCompleteIsNever)
    d.xfer.status[1] = TRACKXFERDONE_NEVER;
  else if (d.xfer.complete)
    d.xfer.status[1] = TRACKXFERDONE_CHECKED;

  if (!d.linker_available)
    d.xfer.status[2] = TRACKXFERDONE_NEVER;
  else if (p.flags&PFLAGS_XFER_BACKLINK)
    d.xfer.status[2] = TRACKXFERDONE_CHECKED;
  if (p.flags&PFLAGS_XFER_DELETE)
    d.xfer.status[3] = TRACKXFERDONE_CHECKED;

  for (i = 0; i < 4; ++i) {
    if (!(d.xfer.status[i] & TRACKXFERDONE_NEVER)) {
      d.xfer.choice_map[choices] = i;
      ++choices;

      /* calculate list width */
      SysCopyStringResource(str, XferMenuOptionsStrings + i);
      n = FntCharsWidth(str, StrLen(str));
      width = Max(width, n);
    }
  }

  LstSetDrawFunction(list, XferDoneListDrawFunc);
  LstSetListChoices(list, 0, choices);
  LstSetHeight(list, Min(choices, 10));
  FrmGetObjectBounds(frm, listIdx, &frame);
  frame.topLeft.y = 144 - frame.extent.y - 1; /* -1 to compensate for white border */
  frame.extent.x = width + 15 + 6;
  FrmSetObjectBounds(frm, listIdx, &frame);
  WinGetFramesRectangle(popupFrame, &frame, &popFrame);
  WinGetFramesRectangle(rectangleFrame, &popFrame, &popShadowFrame);

  for (i = 0; i < choices; ++i)
    RctSetRectangle(&bounds[i+1], frame.topLeft.x, frame.topLeft.y + 10 * i, 
		    frame.extent.x, 10);

  /* Save the bits of the whole menu */
  offscreenH = WinSaveBits(&popShadowFrame, &err);
  if (err) abort();

  /* None selected */
  LstSetSelection(list, -1);

  FrmShowObject(frm, listIdx);
  WinEraseRectangle(&popShadowFrame, 0);
  LstDrawList(list);
  WinEraseRectangleFrame(rectangleFrame, &frame);
  WinDrawRectangleFrame(popupFrame, &frame);

  do {
    EvtGetPen(&x, &y, &penDown);
    if (!state || !RctPtInRectangle(x, y, &bounds[state-1])) {
      on_button = false;
      for (i = 1; i <= choices + 1; i++) {
	if ((state != i) && RctPtInRectangle(x, y, &bounds[i-1])) {
	  /* Invert the new state */
	  LstSetSelection(list, i - 2);
	  LstDrawList(list);
	  WinEraseRectangleFrame(rectangleFrame, &frame);
	  WinDrawRectangleFrame(popupFrame, &frame);
	  
	  SelectAndDrawButton(btn, i == 1);
	  
	  state = i;
	  on_button = true;
	}
      }

      if (state && !on_button) {
	/* Moved off the current button */
	LstSetSelection(list, -1);
	LstDrawList(list);
	WinEraseRectangleFrame(rectangleFrame, &frame);
	WinDrawRectangleFrame(popupFrame, &frame);

	if (state == 1) 
	  SelectAndDrawButton(btn, false);
	state = 0;
      }
    }
  } while (penDown);

  FrmHideObject(frm, listIdx);
  LstEraseList(list);

  /* Restore the framed rect */
  WinRestoreBits(offscreenH, popShadowFrame.topLeft.x, popShadowFrame.topLeft.y);

  /* Unselect the button */
  SelectAndDrawButton(btn, false);

  /* Finish up if we just tapped the button */
  if (RctPtInRectangle(x, y, &bounds[0])) {
    FinishXferMode();
    
    /* Restore the old draw state */
    WinPopDrawState();
    return;
  }

  /* Change the setting for goto or delete */
  for (i = 1; i <= choices; i++) {
    if (RctPtInRectangle(x, y, &bounds[i])) {
      clicked_on = i;
      break;
    }
  }

  if (clicked_on) 
    clicked_on = d.xfer.choice_map[clicked_on-1] + 1;

  switch (clicked_on) {
  case 1: /* Goto */
    if (d.xfer.status[0] & TRACKXFERDONE_CHECKED)
      p.flags &= ~PFLAGS_XFER_GOTO;
    else if (!d.xfer.status[0])
      p.flags |= PFLAGS_XFER_GOTO;
    break;
  case 2: /* Complete */
    if (d.xfer.status[1] & TRACKXFERDONE_CHECKED)
      d.xfer.complete = false;
    else if (!d.xfer.status[1])
      d.xfer.complete = true;
    break;
  case 3: /* BackLink */
    if (d.xfer.status[2] & TRACKXFERDONE_CHECKED)
      p.flags &= ~PFLAGS_XFER_BACKLINK;
    else if (!d.xfer.status[2]) {
      p.flags |= PFLAGS_XFER_BACKLINK;
      p.flags &= ~PFLAGS_XFER_DELETE; /* No delete if backlink */
    }
    break;
  case 4: /* Delete */
    if (d.xfer.status[3] & TRACKXFERDONE_CHECKED)
      p.flags &= ~PFLAGS_XFER_DELETE;
    else if (!d.xfer.status[3]) {
      p.flags |= PFLAGS_XFER_DELETE;
      p.flags &= ~PFLAGS_XFER_BACKLINK; /* No backlink if delete */
    }
    break;
  }

  /* Click and redraw the button */
  if (clicked_on) {
    DrawXferDoneButton(btn);
    DynBtnDraw(btn);
    
    if (d.xfer.status[clicked_on-1] & TRACKXFERDONE_ALWAYS)
      SndPlaySystemSound(sndWarning);
    else
      SndPlaySystemSound(sndClick);
  }

  /* Restore the old draw state */
  WinPopDrawState();
}
예제 #5
0
파일: gadget.c 프로젝트: timn/unimatrix
/*****************************************************************************
* Function: GadgetHintTap
*
* Description: Handles penDown events (taps) on the hint gadget
*****************************************************************************/
void
GadgetHintTap(FormGadgetType *pGadget, EventType *event)
{
  //you may find it useful to track if they
  //lift the pen still within the boundaries of the gadget
  Boolean isPenDown = true;
  Int16 newPointX, newPointY, startPointX, startPointY;
  UInt16 index;
  RectangleType bounds, rect;
  Char noteSymb[2] = { GADGET_NOTESYMBOL, 0 };
  FontID oldFont;
  Boolean drawn=false;
  IndexedColorType curForeColor, curBackColor, curTextColor;

  // This is just needed since we do not want to access internal structure
  // data directly in FormGadgetType (need rect field below)
  index = TNGetObjectIndexFromPtr(FrmGetActiveForm(), pGadget);
  FrmGetObjectBounds(FrmGetActiveForm(), index, &bounds);

  oldFont = FntSetFont(symbolFont);
  RctSetRectangle(&rect,
                  bounds.topLeft.x+1,  // +1 for border
                  bounds.topLeft.y+1, // Put VALUE BELOW here.... +top+1 removed because of own Gadget
                  bounds.extent.x-3, bounds.extent.y - 3); // -4 for bottom border
  RctSetRectangle(&rect, rect.topLeft.x+rect.extent.x-8,
                         rect.topLeft.y+rect.extent.y-12,
                         FntLineWidth(noteSymb, 1), FntLineHeight());


  //track the pen down event
  EvtGetPen(&newPointX, &newPointY, &isPenDown);
  startPointX = newPointX;
  startPointY = newPointY;
  while (isPenDown){
    EvtGetPen(&newPointX, &newPointY, &isPenDown);

    if (gHintNote) {
      if (! drawn && RctPtInRectangle(newPointX, newPointY, &rect)) {
        curForeColor = WinSetForeColor(UIColorGetTableEntryIndex(UIObjectSelectedForeground));
        curBackColor = WinSetBackColor(UIColorGetTableEntryIndex(UIObjectSelectedFill));
        curTextColor = WinSetTextColor(UIColorGetTableEntryIndex(UIObjectSelectedForeground));
        TNDrawCharsToFitWidth(noteSymb, &rect);
        WinSetForeColor(curForeColor);
        WinSetForeColor(curBackColor);
        WinSetForeColor(curTextColor);
        drawn = true;
      } else if (drawn && ! RctPtInRectangle(newPointX, newPointY, &rect)) {
        curForeColor = WinSetForeColor(UIColorGetTableEntryIndex(UIObjectForeground));
        curBackColor = WinSetBackColor(UIColorGetTableEntryIndex(UIObjectFill));
        curTextColor = WinSetTextColor(UIColorGetTableEntryIndex(UIObjectForeground));
        TNDrawCharsToFitWidth(noteSymb, &rect);
        WinSetForeColor(curForeColor);
        WinSetForeColor(curBackColor);
        WinSetForeColor(curTextColor);
        drawn = false;
      }
    }

  }

  FntSetFont(oldFont);

  if (gHintNote && RctPtInRectangle(newPointX, newPointY, &rect)) {
    NoteSet(GadgetGetHintTimeIndex(), FORM_main);
    FrmPopupForm(NewNoteView);
  } // else outside gadget bounds -> do nothing
}
예제 #6
0
파일: gadget.c 프로젝트: timn/unimatrix
/*****************************************************************************
* Function: GadgetTap
*
* Description: Handles penDown events (taps) on the gadget
*****************************************************************************/
void
GadgetTap(FormGadgetType *pGadget, EventType *event)
{
  //you may find it useful to track if they
  //lift the pen still within the boundaries of the gadget
  Boolean isPenDown = true;
  Int16 newPointX, newPointY, startPointX, startPointY;
  UInt16 index;
  RectangleType bounds;

  // This is just needed since we do not want to access internal structure
  // data directly in FormGadgetType (need rect field below)
  index = TNGetObjectIndexFromPtr(FrmGetActiveForm(), pGadget);
  FrmGetObjectBounds(FrmGetActiveForm(), index, &bounds);

  //track the pen down event
  EvtGetPen(&newPointX, &newPointY, &isPenDown);
  startPointX = newPointX;
  startPointY = newPointY;
  while (isPenDown){
    EvtGetPen(&newPointX, &newPointY, &isPenDown);
  }

  if (RctPtInRectangle(newPointX, newPointY, &bounds)) {
    /* the pen up was also in the gadget
       This can mean two things:
       1) we got a strike command
       2) a field was tapped
    */
    RectangleType topRight, bottomRight;
    Boolean found=false, foundTime=false;
    MemHandle m;
    TimeDBRecord *t;
    UInt16 index=0, wantCourse=0, tmp3_4th=0;
    GadgetTimeListType *gtl;
    TNlist *tmpl;

    /* Check for stroke commands */

    tmp3_4th = (3 * bounds.extent.x) / 4;
    RctSetRectangle(&topRight,
                    bounds.topLeft.x+ tmp3_4th,
                    bounds.topLeft.y,
                    bounds.extent.x - tmp3_4th,
                    bounds.extent.y/2
                   );
    RctSetRectangle(&bottomRight,
                    bounds.topLeft.x + tmp3_4th,
                    bounds.topLeft.y + (bounds.extent.y/2),
                    bounds.extent.x - tmp3_4th,
                    bounds.extent.y / 2
                   );

    if (RctPtInRectangle(startPointX, startPointY, &bottomRight) &&
        RctPtInRectangle(newPointX, newPointY, &topRight) ) {
      // Stroke Command: BACK
      GadgetDrawStep(winUp);
      return;
    } else if (RctPtInRectangle(startPointX, startPointY, &topRight) &&
               RctPtInRectangle(newPointX, newPointY, &bottomRight) ) {
      // Stroke Command: NEXT
      GadgetDrawStep(winDown);
      return;
    }


    tmpl = gGadgetTimeList;
    while (tmpl != NULL) {
      gtl = (GadgetTimeListType *)tmpl->data;
      if (RctPtInRectangle(newPointX, newPointY, &(gtl->rect))) {
	m = DmQueryRecord(DatabaseGetRef(), gtl->index);
        if (m) {
          // mt may be null, for example if next is drawn after delete!
          t = (TimeDBRecord *)MemHandleLock(m);

	  // we got a match
	  wantCourse = t->course;
	  gTimeIndex = gtl->index;
	  foundTime  = true;

	  MemHandleUnlock(m);
	}
      }
      tmpl = tmpl->next;
    }

    // Search for the clicked time
    if (foundTime) {
      index = 0;
      while(! found && ((m = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat())) != NULL)) {
	Char *s = (Char *)MemHandleLock(m);
	if (s[0] == TYPE_COURSE) {
	  CourseDBRecord c;
	  UnpackCourse(&c, s);
	  if (c.id == wantCourse) {
	    SndPlaySystemSound(sndClick);
	    gCourseIndex = index;
	    found=true;
	  }
	}
	MemHandleUnlock(m);
	index += 1;
      }
    }

    if (found && foundTime) {
      GadgetDrawHintCurrent();
    } else {
      SndPlaySystemSound(sndError);
    }

  } // else outside gadget bounds -> do nothing

}