www.pudn.com > 6027_HD65.rar > goto.c


/**********************************************************************/ 
/***************    MTK CONFIDENTIAL & COPYRIGHTED     ****************/ 
/***************                                       ****************/ 
/***************  $Modtime:: 04/05/04 3:20p    $       ****************/ 
/***************  $Revision:: 3                $       ****************/ 
/***************                                       ****************/ 
/***************   Description : Goto State Machine    ****************/ 
/***************                                       ****************/ 
/***************       Company : MediaTek Inc.         ****************/ 
/***************    Programmer : Megaa Lin             ****************/ 
/**********************************************************************/ 
#define _GOTO_C_ 
//#define SIMP_GOTO1 
//#define SIMP_GOTO2 
 
#include "general.h" 
#include "osdshow.h" 
 
#pragma NOAREGS 
 
#ifdef PLAYER_GOTO 
 
static void vGotoInitState(void) large; 
 
static void vRedrawGotoItem(BYTE fgClear) large; 
static void vGotoHLItem(BYTE fgShow) large; 
 
static void vInvokeFun(BYTE bState, BYTE fgDeal) large; 
static void vGotoBackMain(void) large; 
 
static void vRedrawGotoAudioItem(BYTE bAtNs) large; 
static void vRedrawGotoSubtItem(BYTE bStNs) large; 
static void vRedrawGotoReptItem(BYTE bRptModeNum) large; 
static void vRedrawGotoTimedispItem(BYTE bTDModeNum) large; 
static void vGotoAudioHLItem(BYTE fgShow) large; 
static void vGotoSubtHLItem(BYTE fgShow) large; 
static void vGotoReptHLItem(BYTE fgShow) large; 
static void vGotoTimedispHLItem(BYTE fgShow) large; 
 
static void vGotoOsdLangKey(void) large; 
 
static void vGotoClose(void) large; 
 
static BYTE bGotoTotalItem(void) large; 
static void vSolidRect(BYTE bWBIdx, WORD wSX, WORD wSY, WORD wEX, WORD wEY, BYTE bCol) large; 
 
static void v2DigitInputHandler(BYTE bCurr, BYTE bTotal, BYTE bUopId, WORD wY) large; 
static void vRedrawGotoItemPage(BYTE bTotal, WORD wMsgIdx, void (*pvFun)(BYTE, BYTE, BYTE) large) large; 
static void vGotoHLItemPage(BYTE fgShow, BYTE bTotal, void (*pvFun)(BYTE, BYTE, BYTE) large) large; 
static void vShowGotoAudioStr(BYTE bAtNo, BYTE bYPos, BYTE bDummy) large; 
static void vShowGotoSubtStr(BYTE bStNo, BYTE bYPos, BYTE bStNs) large; 
static void vShowGotoReptStr(BYTE bReptNo, BYTE bYPos, BYTE bDummy) large; 
static void vShowGotoTimeDispStr(BYTE bTDNo, BYTE bYPos, BYTE bDummy) large; 
static void vPullDownMenuHandler(void) large; 
static void vTimeInputHandler(BYTE fgDeal, BYTE bHH, BYTE bMM, BYTE bSS, BYTE bYPos, BYTE bUopId, void (*pvFun)() large) large; 
static void v2DigitFieldShower(BYTE bState, BYTE bNo, BYTE bNs) large; 
static void vTimeFieldShower(BYTE bState, BYTE bHH, BYTE bMM, BYTE bSS) large; 
 
 
#define fgIsTimeSearchAllow()   ((fgCheckUopBlock(SV_NV_TIME_PLAY) == FALSE) && \ 
                                 (fgCheckUopBlock(SV_NV_TIME_SEARCH) == FALSE)) 
 
#define fgIsAudioChangeAllow()  (fgCheckUopBlock(SV_NV_A_CHANGE) == FALSE) 
 
#ifdef DVD_NO_PTT_PLAY_UOP_BLOCK 
  #define fgIsPTTSearchAllow()  (fgCheckUopBlock(SV_NV_TIME_SEARCH) == FALSE) 
#else 
  #define fgIsPTTSearchAllow()  ((fgCheckUopBlock(SV_NV_PTT_PLAY) == FALSE) && \ 
                                 (fgCheckUopBlock(SV_NV_TIME_SEARCH) == FALSE)) 
#endif 
 
#define fgIsTTLSearchAllow()    (fgCheckUopBlock(SV_NV_TITLE_PLAY) == FALSE) 
 
 
static code strucGotoItem _prGotoItemDVD[GOTO_TOTAL_ITEM_DVD] = 
{ 
  { STGOTO_DVD_TITLE, OSD_MSG_TITLE_G }, 
  { STGOTO_DVD_CHAPTER, OSD_MSG_CHAPTER_G }, 
  { STGOTO_DVD_AUDIO, OSD_MSG_AUDIO_SETTING }, 
  { STGOTO_DVD_SUBTITLE, OSD_MSG_SUBTITLE_SETTING }, 
  { STGOTO_DVD_ANGLE, OSD_MSG_ANGLE_SETTING }, 
  { STGOTO_DVD_TIME, OSD_MSG_TT_TIME_G }, 
  { STGOTO_DVD_TIME_CH, OSD_MSG_CH_TIME_G }, 
  { STGOTO_DVD_REPEAT, OSD_MSG_REPEAT }, 
  { STGOTO_DVD_TIMEDISP, OSD_MSG_TIMEDISP_G } 
 
}; 
 
static code strucGotoItem _prGotoItemVCD[GOTO_TOTAL_ITEM_VCD] = 
{ 
  { STGOTO_VCD_TITLE, OSD_MSG_TRACK_G }, 
#ifdef GOTO_VCD_SEGMENT 
  { STGOTO_VCD_CHAPTER, OSD_MSG_SEGMENT_G }, 
#endif 
  { STGOTO_VCD_TIME, OSD_MSG_DISC_TIME_G }, 
  { STGOTO_VCD_TIME_CH, OSD_MSG_TRK_TIME_G }, 
  { STGOTO_VCD_REPEAT, OSD_MSG_REPEAT }, 
  { STGOTO_VCD_TIMEDISP, OSD_MSG_TIMEDISP_G } 
}; 
 
static code WORD _pwGotoPbcIcon[] = 
{ 
  /* SV_PLAY  */ OSD_MSG_ICON_PLAY, 
  /* SV_FF    */ OSD_MSG_ICON_FFX, 
  /* SV_SF    */ OSD_MSG_ICON_SFX, 
  /* SV_FR    */ OSD_MSG_ICON_FRX, 
  /* SV_SR    */ OSD_MSG_ICON_SRX, 
  /* SV_PAUSE */ OSD_MSG_ICON_PAUSE, 
  /* SV_STEP  */ OSD_MSG_ICON_STEP 
}; 
 
 
static xdata strucGotoItem *_prGotoItem; 
static xdata BYTE _bGotoState; 
static xdata BYTE _bGotoCurItem; 
static xdata BYTE _bGotoBeg; 
static xdata BYTE _bInputPos; 
static xdata BYTE _bInputBeg; 
static xdata BYTE _bInputNum; 
static xdata BYTE _bTimeHH; 
static xdata BYTE _bTimeMM; 
static xdata BYTE _bTimeSS; 
 
static xdata BYTE _bWBGotoPanel; 
static xdata BYTE _bWBGotoMenu; 
 
static BYTE bGotoTotalItem(void) large 
{ 
  if (fgIsDvdPlay()) 
    return (GOTO_TOTAL_ITEM_DVD); 
  else if (fgIsVcdPlay()) 
    return (GOTO_TOTAL_ITEM_VCD); 
} 
 
// megaa downsize begin 
static void vSolidRect(BYTE bWBIdx, WORD wSX, WORD wSY, WORD wEX, WORD wEY, BYTE bCol) large 
{ 
  _wStartX = wSX; 
  _wStartY = wSY; 
  _wEndX = wEX; 
  _wEndY = wEY; 
  vRectangle(bWBIdx, 0, 0, TRUE, bCol); 
} 
// megaa downsize end 
 
void vGotoShowIcon(WORD wMsgIdx, BYTE *pbStr) large 
{ 
  vSolidRect(_bWBGotoMenu, GOTO_STATUS_ICON_X + 40, GOTO_STATUS_ICON_Y, 
             GOTO_STATUS_ICON_X + 120, GOTO_STATUS_ICON_Y + LINE_HEIGHT, 0); 
  vSetMsgCol4(_bWBGotoMenu, 0, 0, 0, 2); 
 
  if (bSharedInfo(SI_NTSC_PAL) == SV_PAL) 
  { 
    vOsdPosPasteArg(OSD_POS_GOTO_ICON_P, wMsgIdx, pbStr, 0); 
  } 
  else 
  { 
    vOsdPosPasteArg(OSD_POS_GOTO_ICON, wMsgIdx, pbStr, 0); 
  }    	 
} 
 
// show up/down mark 
void vGotoShowUDMark(BYTE bBegPos, BYTE bTotal) large 
{ 
  if (bBegPos > 0) 
  { 
    vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
    vOsdPasteMsgXY(GOTO_MARK_X, GOTO_ITEM_BEGIN_Y + 4, 
                   _bWBGotoMenu, OSD_MSG_MARK_UP); 
  } 
  if (bBegPos + GOTO_PAGE_ITEM_NUM < bTotal) 
  { 
    vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
    vOsdPasteMsgXY(GOTO_MARK_X, 
                   GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * (GOTO_PAGE_ITEM_NUM - 1) + 2, 
                   _bWBGotoMenu, OSD_MSG_MARK_DOWN); 
  } 
} 
 
void vGotoInitState(void) large 
{ 
  BYTE bPbcState = bSharedInfo(SI_PBC_STATE); 
  BYTE bAuxCtrl = bSharedInfo(SI_USR_AUX_CTRL); 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
  BYTE bVal = bSharedInfo(SI_PBC_SPEED); 
  BYTE bTvNtscPal = bSharedInfo(SI_NTSC_PAL); 
  BYTE bPNHeight; 
  BYTE pbStr[] = { 2, ' ', ' ' }; 
   
  _rOsdStateCtx.fgGotoShow = FALSE; 
 
  if (bTvNtscPal == SV_PAL) 
  { 
    _bWBGotoPanel = WB_GOTO_PANEL_P; 
    _bWBGotoMenu = WB_GOTO_MENU_P; 
    bPNHeight = PNHEIGHT; 
  } 
  else 
  { 
    _bWBGotoPanel = WB_GOTO_PANEL; 
    _bWBGotoMenu = WB_GOTO_MENU; 
    bPNHeight = 0; 
  } 
   
  if (fgIsDvdPlay()) 
    _prGotoItem = _prGotoItemDVD; 
  else if (fgIsVcdPlay()) 
    _prGotoItem = _prGotoItemVCD; 
   
  if (bPbcState == SV_STOP) 
  { 
    vGotoExit(); 
    return; 
  } 
 
  _rOsdStateCtx.bGotoTimeType = GOTO_SHOW_TITLE_ELAPSED; 
  _rOsdStateCtx.fgGotoShow = TRUE; 
   
  /* 
  if (fgIsVcdPlay()) 
  {   
    // force PBC always off in Goto 
    if (bSharedInfo(SI_PBC_SWITCH) == SV_PBC_ON) 
    { 
      if (bSharedInfo(SI_TRACK_NO) == 0)  // in menu?? 
      { 
        // goto play track 1 directly 
        // UOP_TRACK_PLAY will automatically switch PBC off 
        vSendUopCmd(UOP_TRACK_PLAY, 1, 0, 0); 
        // zoom again because jumping out of menu will return normal size 
        //vSendUopCmd(UOP_ZOOM_IN, SV_ZOOM_41, 1, 0x87); 
      } 
      else 
      { 
        vSendUopCmd(UOP_PBC_SWITCH, 0, 0, 0); 
      } 
    } 
  } 
  */ 
 
  // change display mode 
  vOsdShowWb(OSD_WB_FULL_SCR); 
   
  // hide HL, disable change color 
  // ??? 
// megaa downsize begin 
  //vChgColDis(); 
  //vHideHL(HL_1); 
  //vHideHL(HL_2); 
// megaa downsize end 
   
  if (bTvNtscPal == SV_PAL) 
  { 
    vSendUopCmd(UOP_ZOOM_IN, SV_ZOOM_41, 2, 0x88); 
  } 
  else 
  { 
    vSendUopCmd(UOP_ZOOM_IN, SV_ZOOM_41, 1, 0x88); 
  } 
 
  _bGotoState = STGOTO_MAIN;  // current state is in main menu 
  _bGotoCurItem = 0;          // point to the first item 
  _bGotoBeg = 0;              // begin from the first item 
  _bInputPos = 0xFF; 
  _bInputBeg = 0xFF; 
  _bInputNum = 0; 
  _bTimeHH = _bTimeMM = _bTimeSS = 0; 
   
  // create WBs 
  // WB creation and setup stuff here 
// megaa downsize begin 
  vCreateWB(_bWBGotoMenu, TRUE); 
  vCreateWB(_bWBGotoPanel, TRUE); 
  vSetWBTcColor(_bWBGotoMenu); 
  vSetWBTcColor(_bWBGotoPanel); 
  vSetTransEn(_bWBGotoPanel, 0); 
  vEnableWB(_bWBGotoMenu); 
  vEnableWB(_bWBGotoPanel);   
// megaa downsize end 
   
  // draw menu rectangles 
  /* 
  vSolidRect(_bWBGotoMenu,   // fill menu area with black 
             0, 0, GOTO_MENU_WIDTH - 1, GOTO_MENU_HEIGHT - 1, 2); 
  */ 
  vFillWB(_bWBGotoMenu, 2); 
  vSolidRect(_bWBGotoMenu,   // menu title strip 
             GOTO_WINDOW_BEGIN_X, 0, GOTO_WINDOW_END_X, GOTO_ITEM_BEGIN_Y - 3, 
             0); 
  vSolidRect(_bWBGotoMenu,   // background for playtype icon 
             GOTO_WINDOW_BEGIN_X, GOTO_ITEM_BEGIN_Y - 2, 
             GOTO_PANEL_WIDTH + 9, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 5, 
             13); 
  vSolidRect(_bWBGotoMenu,   // background for menu area 
             GOTO_PANEL_WIDTH + 10, GOTO_ITEM_BEGIN_Y - 2, 
             GOTO_WINDOW_END_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 5, 
             3); 
   
  // draw the bottom black strip 
  vSolidRect(_bWBGotoMenu, 0, GOTO_MENU_HEIGHT - 23, 
             GOTO_MENU_WIDTH - 1, GOTO_MENU_HEIGHT - 1, 2); 
  // draw the bottom status strip 
  vSolidRect(_bWBGotoMenu, GOTO_WINDOW_BEGIN_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 6, 
             GOTO_WINDOW_END_X, GOTO_MENU_HEIGHT - 19, 0); 
  vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 4); 
  vOsdPasteMsgXY(GOTO_BITRATE_X - 95, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 7, 
                 _bWBGotoMenu, OSD_MSG_BITRATE_G); 
 
  // paste round style corner bitmaps 
//  vOsdPasteBmpXY(24, 0, _bWBGotoMenu, BMP_LT_CORNER); 
//  vOsdPasteBmpXY(24, GOTO_MENU_HEIGHT - 20 - 15, _bWBGotoMenu, BMP_LB_CORNER); 
//  vOsdPasteBmpXY(GOTO_WINDOW_END_X - 15, 0, _bWBGotoMenu, BMP_RT_CORNER); 
//  vOsdPasteBmpXY(GOTO_WINDOW_END_X - 15, GOTO_MENU_HEIGHT - 20 - 15, _bWBGotoMenu, BMP_RB_CORNER); 
 
  /* 
  vSolidRect(_bWBGotoPanel,  // fill frame area with black 
             0, 0, 
             GOTO_FRAME_WIDTH - 1, GOTO_FRAME_HEIGHT - 1 + bPNHeight, 
             1); 
  */ 
  vFillWB(_bWBGotoPanel, 1); 
  if (fgIsDvdPlay() && bSharedInfo(SI_V_4_3) == SV_V_16_9) 
  { 
    // draw regular frame and paste corner bitmap 
    vSolidRect(_bWBGotoPanel,  97, 34, 566, GOTO_FRAME_HEIGHT - 5 + bPNHeight, 3); 
    vSolidRect(_bWBGotoPanel,  104, 28, 573, GOTO_FRAME_HEIGHT - 11 + bPNHeight, 2); 
    vSolidRect(_bWBGotoPanel,  108, 32, 569, GOTO_FRAME_HEIGHT - 15 + bPNHeight, 0); 
    vOsdPasteBmpXY(520, 28, _bWBGotoPanel, BMP_GOTO_FRAME_CORNER); 
  } 
  else 
  { 
    // draw regular frame and paste corner bitmap 
    vSolidRect(_bWBGotoPanel, 157, 34, 506, GOTO_FRAME_HEIGHT - 5 + bPNHeight, 3); 
    vSolidRect(_bWBGotoPanel, 164, 28, 513, GOTO_FRAME_HEIGHT - 11 + bPNHeight, 2); 
    vSolidRect(_bWBGotoPanel, 168, 32, 509, GOTO_FRAME_HEIGHT - 15 + bPNHeight, 0); 
    vOsdPasteBmpXY(460, 28, _bWBGotoPanel, BMP_GOTO_FRAME_CORNER); 
  } 
   
  // show current playing media and status 
  if (fgIsDvdPlay()) 
  { 
    bVal = BMP_DVD; 
  } 
  else if (fgIsVcdPlay()) 
  { 
    if (bSharedInfo(SI_DISC_TYPE) == SV_SVCD) 
      bVal = BMP_SVCD; 
    else 
      bVal = BMP_VCD; 
  } 
  vOsdPasteBmpXY(GOTO_PLAYTYPE_ICON_X, GOTO_PLAYTYPE_ICON_Y, 
                 _bWBGotoMenu, bVal); 
   
  vGotoShowIcon(_pwGotoPbcIcon[bPbcState - 2], pbStr); 
#ifndef NEW_SHOW   
  vDVDShowTrick(bPbcState); 
#else 
  vShowTrick(bPbcState);   
#endif 
   
  switch (bAuxCtrl) 
  { 
    case SV_REPEAT_SET_A: 
      vShowGotoPbc(OSD_MSG_ICON_RPT_A); 
      break; 
    case SV_REPEAT_AB: 
      vShowGotoPbc(OSD_MSG_ICON_RPT_AB); 
      break; 
    case SV_REPEAT_NONE: 
    case SV_REPEAT_ABNONE: 
      vShowGotoPbc(OSD_MSG_NULL); 
      break; 
  } 
 
  vRedrawGotoItem(TRUE); 
  vUpdateGotoShow(GOTO_SHOW_PANEL_ALL); 
  vGotoHLItem(TRUE);  // highlight the current pointed-to item 
   
  return; 
} 
 
 
BOOL fgGotoState(void) large 
{ 
  BYTE bPbcState = bSharedInfo(SI_PBC_STATE); 
 
  switch (_bIRKey) 
  { 
    /* check if power down, goto close, open/close key, or open setup menu */ 
#ifdef GOTO_SEPARATE_KEY 
    case GOTO_SEPARATE_KEY: 
#else 
    case IR_GOTO: 
#endif 
      vOsdPosClear(OSD_POS_ZOOM); 
      vSendUopCmd(UOP_ZOOM_IN, SV_ZOOM_1, 0, 0x80); 
      vGotoClose(); 
      vGotoExit(); 
      break; 
 
    //case IR_SETUP:  prevent entering setup in Goto 
    case IR_STOP: 
      vOsdPosClear(OSD_POS_ZOOM); 
      vSendUopCmd(UOP_ZOOM_IN, SV_ZOOM_1, 0, 0x80); 
    case IR_EJECT: 
    case IR_MANUAL_EJECT: 
    case IR_POWER: 
      vGotoClose(); 
      vGotoExit(); 
      return (FALSE); 
     
    case IR_NEXT: 
    case IR_PREV: 
    case IR_VOLUME_UP: 
    case IR_VOLUME_DOWN: 
    case IR_REPEAT: 
    case IR_SET_A: 
    case IR_AUDIO: 
    case IR_SUB_TITLE: 
    case IR_MUTE: 
    case IR_FF: 
    case IR_FR: 
    case IR_SF: 
    case IR_SR:     
    case IR_PAUSE: 
    case IR_PAUSE_STEP: 
    case IR_TITLE_MENU: 
    case IR_ROOT_MENU: 
    case IR_RETURN: 
    case IR_TITLE_PBC: 
    case IR_MENU_PBC: 
    //case IR_PAL_NTSC: 
    case IR_SURROUND: 
      return (FALSE); 
 
    case IR_ANGLE: 
      vSendUopCmd(UOP_NEXT_AGL, 0, 0, 0); 
      return (TRUE); 
 
    case IR_OSD_LANGUAGE: 
      if (_bGotoState != STGOTO_MAIN) // disallowed when not in main Goto state 
      { 
        return (TRUE); 
      } 
      else 
      { 
        vGotoOsdLangKey(); 
        // draw the bottom status strip 
        vSolidRect(_bWBGotoMenu, 
                   GOTO_WINDOW_BEGIN_X + 16, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 6, 
                   GOTO_WINDOW_END_X - 16, GOTO_MENU_HEIGHT - 19, 0); 
        vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 4); 
        vOsdPasteMsgXY(GOTO_BITRATE_X - 95, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 7, 
                       _bWBGotoMenu, OSD_MSG_BITRATE_G); 
        vUpdateGotoShow(GOTO_SHOW_PANEL_ALL); 
        vRedrawGotoItem(TRUE); 
        vGotoHLItem(TRUE); 
        return (TRUE); 
      } 
       
    case IR_ENTER: 
    case IR_PLAY: 
    case IR_PLAY_ENTER: 
      switch (bPbcState) 
      { 
        case SV_FF: 
        case SV_FR: 
        case SV_SF: 
        case SV_SR: 
        case SV_PAUSE: 
        case SV_STEP: 
          return (FALSE);  // don't process this key in Goto 
          break; 
           
        default: 
          break; 
      } 
       
      if (fgIsDvdPlay()) 
      { 
        switch (_bGotoCurItem) 
        { 
          case STGOTO_DVD_CHAPTER: 
          case STGOTO_DVD_TITLE: 
          case STGOTO_DVD_ANGLE: 
          case STGOTO_DVD_TIME: 
          case STGOTO_DVD_TIME_CH: 
            if (_bGotoState != STGOTO_MAIN) 
              break; 
               
            // check disallowed operations 
            if (_bGotoCurItem == STGOTO_DVD_TITLE && !fgIsTTLSearchAllow()) 
              break; 
            if (_bGotoCurItem == STGOTO_DVD_CHAPTER && !fgIsPTTSearchAllow()) 
              break; 
            if ((_bGotoCurItem == STGOTO_DVD_TIME || _bGotoCurItem == STGOTO_DVD_TIME_CH) 
                && !fgIsTimeSearchAllow()) 
              break; 
 
            _bGotoState = _bGotoCurItem; 
            vInvokeFun(_bGotoState, TRUE); 
            if ((_bGotoCurItem == STGOTO_DVD_CHAPTER || _bGotoCurItem == STGOTO_DVD_TIME || _bGotoCurItem == STGOTO_DVD_TIME_CH) && 
                _bGotoState == STGOTO_MAIN) 
            // go back from that state and need to redraw 
            { 
              vRedrawGotoItem(TRUE); 
              vGotoHLItem(TRUE); 
            } 
            break; 
          case STGOTO_DVD_AUDIO: 
            // check disallowed operations 
            if (!fgIsAudioChangeAllow()) 
              break; 
          case STGOTO_DVD_SUBTITLE: 
          case STGOTO_DVD_REPEAT: 
          case STGOTO_DVD_TIMEDISP: 
            if (_bGotoState == STGOTO_MAIN) 
            { 
              _bGotoState = _bGotoCurItem; 
            } 
            vInvokeFun(_bGotoState, TRUE); 
            if (_bGotoState == STGOTO_MAIN) 
            // go back from that state and need to redraw 
            { 
              vRedrawGotoItem(TRUE); 
              vGotoHLItem(TRUE); 
            } 
            break; 
        } 
      } 
      else if (fgIsVcdPlay()) 
      { 
        switch (_bGotoCurItem) 
        { 
          case STGOTO_VCD_TIME_CH: 
            if (bSharedInfo(SI_TRACK_NO) == 0) 
              return (TRUE); 
          case STGOTO_VCD_CHAPTER: 
          case STGOTO_VCD_TITLE: 
          case STGOTO_VCD_TIME: 
            if (_bGotoState != STGOTO_MAIN) 
              break; 
            _bGotoState = _bGotoCurItem; 
            vInvokeFun(_bGotoState, TRUE); 
            if ((_bGotoCurItem == STGOTO_VCD_TIME || _bGotoCurItem == STGOTO_VCD_CHAPTER || _bGotoCurItem == STGOTO_VCD_TIME_CH) 
                && _bGotoState == STGOTO_MAIN) 
            // go back from that state and need to redraw 
            { 
              vRedrawGotoItem(TRUE); 
              vGotoHLItem(TRUE); 
            } 
            break; 
          case STGOTO_VCD_REPEAT: 
            // disallow repeat when PBC on 
            if (bSharedInfo(SI_PBC_SWITCH) == SV_PBC_ON) 
              break; 
          case STGOTO_VCD_TIMEDISP: 
            if (_bGotoState == STGOTO_MAIN) 
            { 
              _bGotoState = _bGotoCurItem; 
            } 
            vInvokeFun(_bGotoState, TRUE); 
            if (_bGotoState == STGOTO_MAIN) 
            // go back from that state and need to redraw 
            { 
              vRedrawGotoItem(TRUE); 
              vGotoHLItem(TRUE); 
            } 
            break; 
        } 
      } 
      break; 
    /* 
      switch (bPbcState) 
      { 
        case SV_PLAY: // show invalid input icon here?? 
                      break; 
         
        case SV_PAUSE: vSendUopCmd(UOP_PAUSE, 0, 0, 0); 
                       vGotoShowPlayIcon(); 
                       break; 
      } 
      break; 
    */ 
 
    case IR_UP: 
      if (_bGotoState == STGOTO_MAIN) 
      { 
        vGotoHLItem(FALSE); 
        if (!_bGotoCurItem--) 
        { 
#ifdef NO_SCROLL_OVER 
          _bGotoCurItem = 0; 
#else 
          // scroll over the top 
          _bGotoCurItem = bGotoTotalItem() - 1; 
          _bGotoBeg = _bGotoCurItem - GOTO_PAGE_ITEM_NUM + 1; 
          if (_bGotoBeg < 0) 
            _bGotoBeg = 0; 
          if (bGotoTotalItem() <= GOTO_PAGE_ITEM_NUM) 
            vRedrawGotoItem(FALSE); 
          else 
            vRedrawGotoItem(TRUE); 
#endif /* NO_SCROLL_OVER */ 
        } 
        else if (_bGotoCurItem < _bGotoBeg && 1) 
        { 
          // scrolling up 
          _bGotoBeg--; 
          vRedrawGotoItem(TRUE); 
        } 
        vGotoHLItem(TRUE); 
           
        break; 
      } 
      goto UP_DOWN_HANDLER;        // temp solution 
      /* 
      if (fgIsDvdPlay()) 
      { 
        switch (_bGotoState) 
        { 
          case STGOTO_DVD_AUDIO: 
          case STGOTO_DVD_SUBTITLE: 
          case STGOTO_DVD_REPEAT: 
          case STGOTO_DVD_TIMEDISP: 
            vInvokeFun(_bGotoState, TRUE); 
            break; 
        } 
      } 
      else if (fgIsVcdPlay()) 
      { 
        switch (_bGotoState) 
        { 
          case STGOTO_VCD_REPEAT: 
          case STGOTO_VCD_TIMEDISP: 
            vInvokeFun(_bGotoState, TRUE); 
            break; 
        } 
      } 
      break; 
      */ 
 
    case IR_DOWN: 
      if (_bGotoState == STGOTO_MAIN) 
      { 
        vGotoHLItem(FALSE); 
        _bGotoCurItem = ++_bGotoCurItem % bGotoTotalItem(); 
        if (_bGotoCurItem == 0) 
        { 
#ifdef NO_SCROLL_OVER 
          _bGotoCurItem = bGotoTotalItem() - 1; 
#else 
          // scroll over the bottom 
          _bGotoBeg = 0; 
          if (bGotoTotalItem() <= GOTO_PAGE_ITEM_NUM) 
            vRedrawGotoItem(FALSE); 
          else 
            vRedrawGotoItem(TRUE); 
#endif /* NO_SCROLL_OVER */ 
        } 
        else if (_bGotoCurItem >= _bGotoBeg + GOTO_PAGE_ITEM_NUM) 
        { 
          // scrolling down 
          _bGotoBeg++; 
          vRedrawGotoItem(TRUE); 
        } 
        vGotoHLItem(TRUE); 
         
        break; 
      } 
UP_DOWN_HANDLER: 
      if (fgIsDvdPlay()) 
      { 
        switch (_bGotoState) 
        { 
          case STGOTO_DVD_AUDIO: 
          case STGOTO_DVD_SUBTITLE: 
          case STGOTO_DVD_REPEAT: 
          case STGOTO_DVD_TIMEDISP: 
            vInvokeFun(_bGotoState, TRUE); 
            break; 
        } 
      } 
      else if (fgIsVcdPlay()) 
      { 
        switch (_bGotoState) 
        { 
          case STGOTO_VCD_REPEAT: 
          case STGOTO_VCD_TIMEDISP: 
            vInvokeFun(_bGotoState, TRUE); 
            break; 
        } 
      } 
      break; 
     
    case IR_LEFT: 
      if (_bGotoState == STGOTO_MAIN) 
        break; 
      if (fgIsDvdPlay()) 
      { 
        switch (_bGotoState) 
        { 
          case STGOTO_DVD_CHAPTER: 
          case STGOTO_DVD_TITLE: 
          case STGOTO_DVD_ANGLE: 
          case STGOTO_DVD_TIME: 
          case STGOTO_DVD_TIME_CH: 
            vGotoBackMain(); 
            vRedrawGotoItem(FALSE); 
            break; 
          case STGOTO_DVD_AUDIO: 
          case STGOTO_DVD_SUBTITLE: 
          case STGOTO_DVD_REPEAT: 
          case STGOTO_DVD_TIMEDISP: 
            vGotoBackMain(); 
            vRedrawGotoItem(TRUE); 
            break; 
        } 
      } 
      else if (fgIsVcdPlay()) 
      { 
        switch (_bGotoState) 
        { 
          case STGOTO_VCD_CHAPTER: 
          case STGOTO_VCD_TITLE: 
          case STGOTO_VCD_TIME: 
          case STGOTO_VCD_TIME_CH: 
            vGotoBackMain(); 
            vRedrawGotoItem(FALSE); 
            break; 
          case STGOTO_VCD_REPEAT: 
          case STGOTO_VCD_TIMEDISP: 
            vGotoBackMain(); 
            vRedrawGotoItem(TRUE); 
            break; 
        } 
      } 
      vGotoHLItem(TRUE); 
      break; 
     
    case IR_DISPLAY: 
#ifdef GOTO_STATUS_NO_TTCH 
      if (bSharedInfo(SI_NTSC_PAL) == SV_PAL) 
      { 
        vOsdPosClear(OSD_POS_GOTO_DISP_P); 
      } 
      else 
      { 
        vOsdPosClear(OSD_POS_GOTO_DISP); 
      } 
#endif 
      _rOsdStateCtx.bGotoTimeType++; 
      _rOsdStateCtx.bGotoTimeType %= 4; 
      vUpdateGotoShow(GOTO_SHOW_PANEL_TIME); 
      vDealGotoTimedisp(FALSE); 
      break; 
       
    default: 
      if (_bGotoState != STGOTO_MAIN) 
      { 
        vInvokeFun(_bGotoState, TRUE); 
        break; 
      } 
      if (_bIRKey >= IR_INTERNAL_KEY_START) 
      { 
      	if (fgIsNoInputState() && _bIRKey != IR_CMD_DONE) 
      	{ 
          vOsdPosClear(OSD_POS_ZOOM); 
          vSendUopCmd(UOP_ZOOM_IN, SV_ZOOM_1, 0, 0x80); 
          vGotoClose(); 
          vGotoExit(); 
        } 
        return (FALSE); 
      } 
      break; 
  } 
   
  return (TRUE); 
} 
 
// common portion of original vDealGotoChapter and vDealGotoTitle 
static void v2DigitInputHandler(BYTE bCurr, BYTE bTotal, BYTE bUopId, WORD wY) large 
{ 
  BYTE bNum; 
  BYTE pbStr[] = { 5, '1', '2', '/', '3', '4' }; 
   
  pbStr[1] = bCurr / 10 + '0'; 
  pbStr[2] = bCurr % 10 + '0'; 
  pbStr[4] = bTotal / 10 + '0'; 
  pbStr[5] = bTotal % 10 + '0'; 
 
  switch (_bIRKey) 
  { 
    case IR_PLAY: 
    case IR_ENTER: 
    case IR_PLAY_ENTER: 
      if (_bInputPos == 0xFF) 
      { 
        _bInputPos = 0; 
        _bInputNum = 0; 
        pbStr[1] = '_'; 
        pbStr[2] = '0'; 
        vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 4); 
        vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
      } 
      break; 
       
    case IR_NUM0: 
    case IR_NUM1: 
    case IR_NUM2: 
    case IR_NUM3: 
    case IR_NUM4: 
    case IR_NUM5: 
    case IR_NUM6: 
    case IR_NUM7: 
    case IR_NUM8: 
    case IR_NUM9: 
      pbStr[1] = '0' + _bInputNum / 10; 
      pbStr[2] = '0' + _bInputNum % 10; 
      bNum = _bIRKey - IR_NUM0; 
      if (_bInputPos == 0) 
      { 
        if (bNum > (bTotal / 10))         // invalid input 
          break; 
        _bInputNum = 10 * bNum; 
        pbStr[1] = '0' + bNum; 
        pbStr[2] = '_'; 
        _bInputPos++; 
      } 
      else 
      { 
        if (_bInputNum + bNum > bTotal) 
          break;  // input exceeding valid range 
        if (_bInputNum + bNum == 0) 
          break;  // input 00 
        _bInputNum += bNum; 
        pbStr[2] = '0' + bNum; 
        _bInputPos++; 
      } 
      vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 4); 
      vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
       
      if (_bInputPos == 2)  // input completed (2-digit) 
      { 
        vSendUopCmd(bUopId, _bInputNum, 0, 0); 
        vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
        vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
        //vRedrawGotoItem(TRUE); 
        //vGotoHLItem(TRUE); 
        vGotoBackMain(); 
      } 
      break; 
  } 
} 
 
void vDealGotoChapter(BYTE fgDeal) large 
{ 
  BYTE bYPos = (fgIsDvdPlay() ? STGOTO_DVD_CHAPTER : STGOTO_VCD_CHAPTER) - 
                _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
  // when VCD, use PTT as the analogy to DVD's chapter 
  BYTE bChNo = bSharedInfo(fgIsDvdPlay() ? SI_CHAP_NO : SI_PTT_NO); 
  BYTE bChNs = bSharedInfo(fgIsDvdPlay() ? SI_CHAP_NS : SI_PTT_NS); 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
   
  if (!fgDeal) 
  { 
    vShowGotoChapter(); 
    return; 
  } 
   
  if (fgIsDvdPlay() && bSharedInfo(SI_DVD_DOM) != SV_VTSTT_DOM) 
  { 
    vGotoBackMain(); 
    return; 
  } 
 
  v2DigitInputHandler(bChNo, bChNs, UOP_PTT_PLAY, wY); 
} 
 
void vDealGotoTitle(BYTE fgDeal) large 
{ 
  BYTE bYPos = (fgIsDvdPlay() ? STGOTO_DVD_TITLE : STGOTO_VCD_TITLE) - 
                _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
  // when VCD, use TRACK as the analogy to DVD's title 
  BYTE bTtNo = bSharedInfo(fgIsDvdPlay() ? SI_TT_NO : SI_TRACK_NO); 
  BYTE bTtNs = bSharedInfo(fgIsDvdPlay() ? SI_TT_NS : SI_TRACK_NS); 
  BYTE bUopId; 
   
  if (!fgDeal) 
  { 
    vShowGotoTitle(); 
    return; 
  } 
   
  if (fgIsDvdPlay()) 
    bUopId = UOP_TITLE_PLAY; 
  else if (fgIsVcdPlay()) 
    bUopId = UOP_TRACK_PLAY; 
   
  v2DigitInputHandler(bTtNo, bTtNs, bUopId, wY); 
} 
 
// the following global variables are for vRedrawGotoItemPage() only 
// !!! if we use auto variables instead, there will be strange error !!! 
static xdata void (*_pvFunBak)(BYTE, BYTE, BYTE) large; 
static BYTE xdata _bCntI; 
static BYTE xdata _bTotal; 
 
static void vRedrawGotoItemPage(BYTE bTotal, WORD wMsgIdx, void (*pvFun)(BYTE, BYTE, BYTE) large) large 
{ 
  _bTotal = bTotal; 
  _pvFunBak = pvFun; 
   
  // clear all pasted messages 
  vSolidRect(_bWBGotoMenu, GOTO_PANEL_WIDTH + 11, GOTO_ITEM_BEGIN_Y - 2, 
             GOTO_WINDOW_END_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 5, 3); 
 
  // draw the top green rectangle and paste menu title 
  vSolidRect(_bWBGotoMenu, GOTO_LITEM_X, 0, 
             GOTO_WINDOW_END_X - 17, GOTO_ITEM_BEGIN_Y - 3, 0); 
  vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 4); 
  vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y - 34, 
                 _bWBGotoMenu, wMsgIdx); 
   
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  for (_bCntI = 0; _bCntI < GOTO_PAGE_ITEM_NUM; _bCntI++) 
  { 
    if (_bCntI + _bInputBeg >= _bTotal) 
      break; 
    _pvFunBak(_bCntI + _bInputBeg, _bCntI, _bTotal); 
  } 
 
  vGotoShowUDMark(_bInputBeg, _bTotal); 
} 
 
static void vGotoHLItemPage(BYTE fgShow, BYTE bTotal, void (*pvFun)(BYTE, BYTE, BYTE) large) large 
{ 
  BYTE bYPos = _bInputPos - _bInputBeg; 
  BYTE bColor; 
   
  if (fgShow) 
    bColor = 5;  // highlight this item 
  else 
    bColor = 3;  // unhighlight this item 
     
  vSolidRect(_bWBGotoMenu, 
             GOTO_LITEM_X - 23, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos, 
             GOTO_RITEM_X + 125, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * (bYPos + 1) - 1, 
             bColor); 
  vSetMsgCol4(_bWBGotoMenu, 0, bColor, 2, 1); 
   
  pvFun(_bInputPos, bYPos, bTotal); 
}   
 
static void vShowGotoAudioStr(BYTE bAtNo, BYTE bYPos, BYTE bDummy) large 
{ 
  BYTE bLcd0, bLcd1; 
  BYTE pbStr[7]; 
  WORD wMsgIdx; 
   
  pbStr[0] = 6; 
  wMsgIdx = wOsdGetAudChMsg(bSharedInfo(wSIItemPos(SI_AUD_LCD_GRP, 17 + bAtNo))); 
  pbStr[1] = bLoByte(wMsgIdx); 
  pbStr[2] = bHiByte(wMsgIdx); 
  wMsgIdx = wOsdGetAudAtrMsg(bSharedInfo(wSIItemPos(SI_AUD_LCD_GRP, 25 + bAtNo))); 
  pbStr[3] = bLoByte(wMsgIdx); 
  pbStr[4] = bHiByte(wMsgIdx); 
  bLcd0 = bSharedInfo(wSIItemPos(SI_AUD_LCD_GRP, 1 + bAtNo * 2)); 
  bLcd1 = bSharedInfo(wSIItemPos(SI_AUD_LCD_GRP, 2 + bAtNo * 2)); 
  wMsgIdx = wOsdGetLcdMsg(bLcd0, bLcd1); 
  pbStr[5] = bLoByte(wMsgIdx); 
  pbStr[6] = bHiByte(wMsgIdx); 
 
  vOsdPasteMsgXYArg(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + bYPos * LINE_HEIGHT, 
                    _bWBGotoMenu, OSD_MSG_AUDIO_G, pbStr); 
} 
static void vShowGotoSubtStr(BYTE bStNo, BYTE bYPos, BYTE bStNs) large 
{ 
  BYTE bLcd0, bLcd1; 
  WORD wMsgIdx; 
 
  if (bStNo == bStNs - 1) 
    wMsgIdx = OSD_MSG_OFF; 
  else if (bStNo <= 15) 
  { 
    bLcd0 = bSharedInfo(wSIItemPos(SI_SP_LCD_GRP0, 1 + bStNo * 2)); 
    bLcd1 = bSharedInfo(wSIItemPos(SI_SP_LCD_GRP0, 2 + bStNo * 2)); 
    wMsgIdx = wOsdGetLcdMsg(bLcd0, bLcd1); 
  } 
  else 
  { 
    bLcd0 = bSharedInfo(wSIItemPos(SI_SP_LCD_GRP1, -31 + bStNo * 2)); 
    bLcd1 = bSharedInfo(wSIItemPos(SI_SP_LCD_GRP1, -30 + bStNo * 2)); 
    wMsgIdx = wOsdGetLcdMsg(bLcd0, bLcd1); 
  } 
   
  vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + bYPos * LINE_HEIGHT, 
                 _bWBGotoMenu, wMsgIdx); 
} 
static void vShowGotoReptStr(BYTE bReptNo, BYTE bYPos, BYTE bDummy) large 
{ 
  WORD pwMsgIdxDVD[] = { OSD_MSG_ICON_RPT_CH, 
                         OSD_MSG_ICON_RPT_TT, 
                         OSD_MSG_ICON_RPT_ALL, 
                         OSD_MSG_OFF }; 
  WORD pwMsgIdxVCD[] = { OSD_MSG_ICON_RPT_TRK, 
                         OSD_MSG_ICON_RPT_ALL, 
                         OSD_MSG_OFF }; 
 
  if (fgIsDvdPlay()) 
  { 
    vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + bYPos * LINE_HEIGHT, 
                   _bWBGotoMenu, pwMsgIdxDVD[bReptNo]); 
  } 
  else if (fgIsVcdPlay()) 
  { 
    vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + bYPos * LINE_HEIGHT, 
                   _bWBGotoMenu, pwMsgIdxVCD[bReptNo]); 
  } 
} 
static void vShowGotoTimeDispStr(BYTE bTDNo, BYTE bYPos, BYTE bDummy) large 
{ 
  WORD pwMsgIdxDVD[] = { OSD_MSG_TITLE_ELAPSED, 
                         OSD_MSG_TITLE_REMAIN, 
                         OSD_MSG_CHAPTER_ELAPSED, 
                         OSD_MSG_CHAPTER_REMAIN }; 
  WORD pwMsgIdxVCD[] = { OSD_MSG_TOTAL_ELAPSED, 
                         OSD_MSG_TOTAL_REMAIN, 
                         OSD_MSG_SINGLE_ELAPSED, 
                         OSD_MSG_SINGLE_REMAIN }; 
 
  if (fgIsDvdPlay()) 
  { 
    vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + bYPos * LINE_HEIGHT, 
                   _bWBGotoMenu, pwMsgIdxDVD[bTDNo]); 
  } 
  else if (fgIsVcdPlay()) 
  { 
    vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + bYPos * LINE_HEIGHT, 
                   _bWBGotoMenu, pwMsgIdxVCD[bTDNo]); 
  } 
} 
 
void vRedrawGotoAudioItem(BYTE bAtNs) large 
{ 
  vRedrawGotoItemPage(bAtNs, OSD_MSG_AUDIO_SETTING, vShowGotoAudioStr); 
} 
void vGotoAudioHLItem(BYTE fgShow) large 
{ 
  vGotoHLItemPage(fgShow, 0, vShowGotoAudioStr); 
} 
 
void vRedrawGotoSubtItem(BYTE bStNs) large 
{ 
  vRedrawGotoItemPage(bStNs, OSD_MSG_SUBTITLE_SETTING, vShowGotoSubtStr); 
} 
void vGotoSubtHLItem(BYTE fgShow) large 
{ 
  BYTE bStNs = bSharedInfo(SI_SPST_NS) + 1;  // additional "OFF" 
   
  vGotoHLItemPage(fgShow, bStNs, vShowGotoSubtStr); 
} 
 
void vRedrawGotoReptItem(BYTE bRptModeNum) large 
{ 
  vRedrawGotoItemPage(bRptModeNum, OSD_MSG_REPEAT, vShowGotoReptStr); 
} 
void vGotoReptHLItem(BYTE fgShow) large 
{ 
  vGotoHLItemPage(fgShow, 0, vShowGotoReptStr); 
} 
 
void vRedrawGotoTimedispItem(BYTE bTDModeNum) large 
{ 
  vRedrawGotoItemPage(bTDModeNum, OSD_MSG_TIMEDISP_G, vShowGotoTimeDispStr); 
} 
void vGotoTimedispHLItem(BYTE fgShow) large 
{ 
  vGotoHLItemPage(fgShow, 0, vShowGotoTimeDispStr); 
} 
 
 
// the following variables are for vPullDownMenuHandler() only 
static xdata void (*_pvHLFun)(BYTE) large; 
static xdata void (*_pvRedrawFun)(BYTE) large; 
 
static void vPullDownMenuHandler(void) large 
{ 
  switch (_bIRKey) 
  { 
    case IR_UP: 
      _pvHLFun(FALSE); 
      if (!_bInputPos--) 
#ifdef NO_SCROLL_OVER 
        _bInputPos = 0; 
#else 
        _bInputPos = _bTotal - 1; 
      if (_bInputPos == _bTotal - 1 && _bTotal > GOTO_PAGE_ITEM_NUM) 
      // scroll over the top 
      { 
        _bInputBeg = _bInputPos - GOTO_PAGE_ITEM_NUM + 1; 
        _pvRedrawFun(_bTotal); 
      } 
      else if (_bInputPos < _bInputBeg) 
      { 
        // scrolling 
        _bInputBeg--; 
        _pvRedrawFun(_bTotal); 
      } 
#endif /* NO_SCROLL_OVER */ 
      _pvHLFun(TRUE); 
      break; 
 
    case IR_DOWN: 
      _pvHLFun(FALSE); 
      _bInputPos = ++_bInputPos % _bTotal; 
#ifdef NO_SCROLL_OVER 
      if (_bInputPos == 0) 
        _bInputPos = _bTotal - 1; 
#else 
      if (_bInputPos == 0 && _bTotal > GOTO_PAGE_ITEM_NUM) 
      // scroll over the bottom 
      { 
        _bInputPos = 0; 
        _bInputBeg = 0; 
        _pvRedrawFun(_bTotal); 
      } 
      else if (_bInputPos >= _bInputBeg + GOTO_PAGE_ITEM_NUM) 
      { 
        // scrolling 
        _bInputBeg++; 
        _pvRedrawFun(_bTotal); 
      } 
#endif /* NO_SCROLL_OVER */ 
      _pvHLFun(TRUE); 
      break; 
  } 
} 
 
 
void vDealGotoAudio(BYTE fgDeal) large 
{ 
  BYTE bAtNo = bSharedInfo(SI_AST_NO); 
  BYTE bAtNs = bSharedInfo(SI_AST_NS); 
  BYTE bType = (bSharedInfo(SI_A_CH_CFG) << 4) | bSharedInfo(SI_A_CODE_MODE); 
  BYTE bLcd0 = bSharedInfo(SI_A_LCD_0); 
  BYTE bLcd1 = bSharedInfo(SI_A_LCD_1); 
  WORD wMsgIdx1, wMsgIdx2; 
  BYTE bCntI; 
 
  if (!fgIsDvdPlay()) 
    return; 
     
  wMsgIdx1 = wOsdGetAudChMsg((bType & 0xf0) >> 4); 
  wMsgIdx2 = wOsdGetLcdMsg(bLcd0, bLcd1); 
 
  if (!fgDeal)  // show current audio setting 
  { 
    vShowGotoAudio(0, wMsgIdx1, wMsgIdx2); 
    return; 
  } 
   
  switch (_bIRKey) 
  { 
    case IR_ENTER: 
    case IR_PLAY: 
    case IR_PLAY_ENTER: 
      if (_bInputPos == 0xFF)  // just enter by pressing PLAY 
      { 
        _bInputPos = bAtNo; 
        if (_bInputPos >= GOTO_PAGE_ITEM_NUM) 
          _bInputBeg = _bInputPos - GOTO_PAGE_ITEM_NUM + 1; 
        else 
          _bInputBeg = 0; 
        vRedrawGotoAudioItem(bAtNs); 
        vGotoAudioHLItem(TRUE); 
        break; 
      } 
      else  // switch to current audio setting 
      { 
        if (bAtNo == _bInputPos)  // don't switch to the same one 
        { 
          vGotoBackMain(); 
          break; 
        } 
        else 
        { 
          bAtNo = _bInputPos; 
        } 
  #ifdef PLAYER_KARAOKE 
        if (fgIsVocalAssistOn()) 
        { 
          vAdspVocalAssist(VOCAL_NO_ASSIST); 
        } 
  #endif /* PLAYER_KARAOKE */ 
        if ((bSharedInfo(SI_PBC_STATE) != SV_PLAY) || 
            (bAtNs <= 1) || (bAtNs > 8) || (bAtNo >= bAtNs)) 
        { 
          //return (UOP_FAIL); 
        } 
        else 
        { 
          vSendUopCmd(UOP_CHANGE_ASTN, bAtNo, 
                      DVD_CHG_AST_OPT2, DVD_CHG_AST_OPT3); 
        } 
        vGotoBackMain(); 
        break; 
      } 
  } 
   
  _pvHLFun = vGotoAudioHLItem; 
  _pvRedrawFun = vRedrawGotoAudioItem; 
  _bTotal = bAtNs; 
  vPullDownMenuHandler(); 
} 
 
 
void vDealGotoSubtitle(BYTE fgDeal) large 
{ 
  BYTE bStNo = bSharedInfo(SI_SPST_NO); 
  BYTE bStNs = bSharedInfo(SI_SPST_NS) + 1;  // additional "OFF" 
  BYTE bCh1 = bSharedInfo(SI_SP_LCD_0); 
  BYTE bCh2 = bSharedInfo(SI_SP_LCD_1); 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
  WORD wMsgIdx; 
  BYTE bCntI; 
 
  if (bDom != SV_VTSTT_DOM)  // force no subtitle selection in non-VTSTT domain 
    bStNs = 1; 
     
  if (bStNo == 0 || bStNs == 1)  // bStNs = 1 when no subtitle available 
    wMsgIdx = OSD_MSG_OFF; 
  else 
    wMsgIdx = wOsdGetLcdMsg(bCh1, bCh2); 
 
  if (!fgDeal)  // show current subtitle setting 
  { 
    vShowGotoSubtitle(wMsgIdx); 
    return; 
  } 
   
  switch (_bIRKey) 
  { 
    case IR_ENTER: 
    case IR_PLAY: 
    case IR_PLAY_ENTER: 
      if (bStNs == 1) 
      { 
        vGotoBackMain(); 
        break; 
      } 
      if (_bInputPos == 0xFF)  // just enter by pressing PLAY 
      { 
        if (bStNo == 0) 
          _bInputPos = bStNs - 1; 
        else 
          _bInputPos = bStNo & 0xBF; 
        if (_bInputPos >= GOTO_PAGE_ITEM_NUM) 
          _bInputBeg = _bInputPos - GOTO_PAGE_ITEM_NUM + 1; 
        else 
          _bInputBeg = 0; 
        vRedrawGotoSubtItem(bStNs); 
        vGotoSubtHLItem(TRUE); 
        break; 
      } 
      else  // switch to current subtitle setting 
      { 
        if (_bInputPos == bStNs - 1) 
          bStNo = 0; 
        else 
          bStNo = (_bInputPos & 0x1f) | 0x40; 
        vSendUopCmd(UOP_CHANGE_SPSTN, bStNo, 0, 0); 
        vGotoBackMain(); 
        break; 
      } 
  } 
   
  _pvHLFun = vGotoSubtHLItem; 
  _pvRedrawFun = vRedrawGotoSubtItem; 
  _bTotal = bStNs; 
  vPullDownMenuHandler(); 
} 
 
 
void vDealGotoAngle(BYTE fgDeal) large 
{ 
  BYTE bAgNo = bSharedInfo(SI_AGL_NO); 
  BYTE bAgNs = bSharedInfo(SI_AGL_NS); 
  BYTE bYPos = STGOTO_DVD_ANGLE - _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
  BYTE pbStr[] = { 3, '1', '/', '2' }; 
  BYTE bNum; 
   
  if (!fgDeal)  // show status only 
  { 
    vShowGotoAngle(); 
    return; 
  } 
 
  if (bAgNo == 0xFF) 
    bAgNo = 1; 
   
  pbStr[1] = bAgNo + '0'; 
  pbStr[3] = bAgNs + '0'; 
 
  switch (_bIRKey) 
  { 
    case IR_PLAY: 
    case IR_ENTER: 
    case IR_PLAY_ENTER: 
      if (_bInputPos == 0xFF) 
      { 
        _bInputPos = 0; 
        _bInputNum = 0; 
        pbStr[1] = '_'; 
        vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 4); 
        vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
      } 
      break; 
       
    //case IR_NUM0: 
    case IR_NUM1: 
    case IR_NUM2: 
    case IR_NUM3: 
    case IR_NUM4: 
    case IR_NUM5: 
    case IR_NUM6: 
    case IR_NUM7: 
    case IR_NUM8: 
    case IR_NUM9: 
      bNum = _bIRKey - IR_NUM0; 
      if (bNum > bAgNs)         // invalid input 
        break; 
      _bInputNum = bNum; 
      pbStr[1] = '0' + bNum; 
      _bInputPos++; 
      vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 4); 
      vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
       
      if (_bInputPos == 1)  // angle input completed 
      { 
        vSendUopCmd(UOP_CHANGE_AGL, _bInputNum, 0, 0); 
        vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
        vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
        vGotoBackMain(); 
      } 
      break; 
  } 
} 
 
 
static void vTimeInputHandler(BYTE fgDeal, BYTE bHH, BYTE bMM, BYTE bSS, BYTE bYPos, BYTE bUopId, void (*pvFun)() large) large 
{ 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
  BYTE pbStr[] = { 7, '_', ':', '0', '0', ':', '0', '0' }; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
  BYTE bNum; 
  BYTE bUopParam; 
 
  if (!fgDeal) 
  { 
    pvFun(); 
    return; 
  } 
 
  if (bUopId == UOP_PTT_TIME_PLAY) 
    bUopParam = SV_TIME_TRACK; 
  else if (bUopId == UOP_TIME_PLAY) 
    bUopParam = SV_TIME_DISC; 
   
  if (BCD2DEC(bMM) >= 60)  // for VCD only, assume max 99:59 
  { 
    bMM = ((BCD_HI(bMM) - 6) << 4) | BCD_LO(bMM); 
    bHH++; 
  } 
       
  switch (_bIRKey) 
  { 
    case IR_PLAY: 
    case IR_ENTER: 
    case IR_PLAY_ENTER: 
      if (fgIsDvdPlay() && bDom != SV_VTSTT_DOM)  // force no time jump in non-VTSTT domain 
      { 
        vGotoBackMain(); 
        break; 
      } 
      if (_bInputPos == 0xFF) 
      { 
        _bInputPos = 0; 
        _bTimeHH = _bTimeMM = _bTimeSS = 0; 
        vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 4); 
        vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
      } 
      break; 
       
    case IR_NUM0: 
    case IR_NUM1: 
    case IR_NUM2: 
    case IR_NUM3: 
    case IR_NUM4: 
    case IR_NUM5: 
    case IR_NUM6: 
    case IR_NUM7: 
    case IR_NUM8: 
    case IR_NUM9: 
      pbStr[1] = '0' + _bTimeHH; 
      pbStr[3] = '0' + _bTimeMM / 10; 
      pbStr[4] = '0' + _bTimeMM % 10; 
      pbStr[6] = '0' + _bTimeSS / 10; 
      pbStr[7] = '0' + _bTimeSS % 10; 
      bNum = _bIRKey - IR_NUM0; 
      if (_bInputPos == 0) 
      { 
        if (bNum > BCD_LO(bHH))  // exceed range 
          break; 
        _bTimeHH = bNum; 
        pbStr[1] = '0' + bNum; 
        _bInputPos++; 
      } 
      else if (_bInputPos <= 2) 
      { 
        if (_bInputPos == 1) 
        { 
          if (bNum > 5)  // invalid input 
            break; 
          if (_bTimeHH == BCD_LO(bHH) && bNum > BCD_HI(bMM)) 
            // exceed range 
            break; 
        } 
        else if (_bInputPos == 2) 
        { 
          if (_bTimeHH == BCD_LO(bHH) && 
              _bTimeMM == BCD_HI(bMM) && 
              bNum > BCD_LO(bMM))  // exceed range 
            break; 
        } 
        _bTimeMM = _bTimeMM * 10 + bNum; 
        pbStr[3] = '0' + _bTimeMM / 10; 
        pbStr[4] = '0' + _bTimeMM % 10; 
        pbStr[_bInputPos + 2] = '0' + bNum; 
        _bInputPos++; 
      } 
      else 
      { 
        if (_bInputPos == 3) 
        { 
          if (bNum > 5)  // invalid input 
            break; 
          if (_bTimeHH == BCD_LO(bHH) && 
              _bTimeMM == BCD2DEC(bMM) && 
              bNum > BCD_HI(bSS))  // exceed range 
            break; 
        } 
        else if (_bInputPos == 4) 
        { 
          if (_bTimeHH == BCD_LO(bHH) && 
              _bTimeMM == BCD2DEC(bMM) && 
              _bTimeSS == BCD_HI(bSS) && 
              bNum > BCD_LO(bSS))  // exceed range 
            break; 
        } 
        _bTimeSS = _bTimeSS * 10 + _bIRKey - IR_NUM0; 
        pbStr[6] = '0' + _bTimeSS / 10; 
        pbStr[7] = '0' + _bTimeSS % 10; 
        pbStr[_bInputPos + 3] = '0' + bNum; 
        _bInputPos++; 
      } 
      if (_bInputPos <= 2) 
        pbStr[_bInputPos + 2] = '_'; 
      else if (_bInputPos <= 4) 
        pbStr[_bInputPos + 3] = '_'; 
      vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 4); 
      vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
       
      if (_bInputPos == 5)  // time input completed 
      { 
        if (fgIsVcdPlay()) 
        { 
          if (bSharedInfo(SI_PBC_SWITCH) == SV_PBC_ON) 
          { 
            // switch to PBC off first 
            vSendUopCmd(UOP_PBC_SWITCH, 0, 0, 0); 
          } 
          if (_bTimeHH > 0)  // for VCD only, assume max 99:59 
          { 
            vSendUopCmd(UOP_TIME_PLAY, bUopParam, _bTimeMM + 60, _bTimeSS); 
          } 
          else 
          { 
            vSendUopCmd(UOP_TIME_PLAY, bUopParam, _bTimeMM, _bTimeSS); 
          } 
        } 
        else 
        { 
          vSendUopCmd(bUopId, _bTimeHH, _bTimeMM, _bTimeSS); 
        } 
        vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
        vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
        //_bTimeHH = _bTimeMM = _bTimeSS = 0; 
        vGotoBackMain(); 
        pvFun(); 
      } 
      break; 
  } 
} 
 
void vDealGotoTime(BYTE fgDeal) large 
{ 
  BYTE bTotalTimeHH = bSharedInfo(SI_TIME_TOTAL_HH); 
  BYTE bTotalTimeMM = bSharedInfo(SI_TIME_TOTAL_MM); 
  BYTE bTotalTimeSS = bSharedInfo(SI_TIME_TOTAL_SS); 
  BYTE pbStr[] = { 7, '_', ':', '0', '0', ':', '0', '0' }; 
  BYTE bYPos = (fgIsDvdPlay() ? STGOTO_DVD_TIME : STGOTO_VCD_TIME) - 
                _bGotoBeg; 
                 
  vTimeInputHandler(fgDeal, bTotalTimeHH, bTotalTimeMM, bTotalTimeSS, 
                    bYPos, UOP_TIME_PLAY, vShowGotoTime); 
} 
 
void vDealGotoTimeCH(BYTE fgDeal) large 
{ 
  BYTE bTotalTimeHH = bSharedInfo(fgIsDvdPlay() ? SI_TIME_TOTAL_CHAPTER_HH : SI_TIME_TOTAL_TRACK_HH); 
  BYTE bTotalTimeMM = bSharedInfo(fgIsDvdPlay() ? SI_TIME_TOTAL_CHAPTER_MM : SI_TIME_TOTAL_TRACK_MM); 
  BYTE bTotalTimeSS = bSharedInfo(fgIsDvdPlay() ? SI_TIME_TOTAL_CHAPTER_SS : SI_TIME_TOTAL_TRACK_SS); 
  BYTE bYPos = (fgIsDvdPlay() ? STGOTO_DVD_TIME_CH : STGOTO_VCD_TIME_CH) - 
                _bGotoBeg; 
                 
  vTimeInputHandler(fgDeal, bTotalTimeHH, bTotalTimeMM, bTotalTimeSS, 
                    bYPos, UOP_PTT_TIME_PLAY, vShowGotoTimeCH); 
} 
 
 
void vDealGotoRepeat(BYTE fgDeal) large 
{ 
  BYTE bMode = bSharedInfo(SI_REPEAT_MODE); 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
  WORD wMsgIdx; 
  BYTE bCntI; 
  BYTE bRptModeNum = (fgIsDvdPlay() ? 4 : 3); 
  BYTE bCurRptModeNo; 
  BYTE pbReptModeDVD[] = { SV_REPEAT_CHAPTER, 
                           SV_REPEAT_TITLE, 
                           SV_REPEAT_ALL, 
                           SV_REPEAT_NONE }; 
  BYTE pbReptModeVCD[] = { SV_REPEAT_TRACK, 
                           SV_REPEAT_ALL, 
                           SV_REPEAT_NONE }; 
 
  switch (bMode) 
  { 
    case SV_REPEAT_ALL: 
      wMsgIdx = OSD_MSG_ICON_RPT_ALL; 
      bCurRptModeNo = fgIsDvdPlay() ? 2 : 1; 
      break; 
 
    case SV_REPEAT_TRACK: 
    case SV_REPEAT_LIST: 
      wMsgIdx = OSD_MSG_ICON_RPT_TRK; 
      bCurRptModeNo = 0; 
      break; 
 
    case SV_REPEAT_TITLE: 
      wMsgIdx = OSD_MSG_ICON_RPT_TT; 
      bCurRptModeNo = 1; 
      break; 
 
    case SV_REPEAT_CHAPTER: 
      wMsgIdx = OSD_MSG_ICON_RPT_CH; 
      bCurRptModeNo = 0; 
      break; 
 
    case SV_REPEAT_NONE: 
    case SV_REPEAT_ABNONE: 
      wMsgIdx = OSD_MSG_OFF; 
      bCurRptModeNo = fgIsDvdPlay() ? 3 : 2; 
      break; 
 
    default: 
      break; 
  } 
     
  if (fgIsDvdPlay() && bDom != SV_VTSTT_DOM)  // force repeat mode off in non-VTSTT domain 
    wMsgIdx = OSD_MSG_OFF; 
   
  if (!fgDeal)  // show current repeat setting 
  { 
    vShowGotoRepeat(wMsgIdx); 
    return; 
  } 
   
  switch (_bIRKey) 
  { 
    case IR_ENTER: 
    case IR_PLAY: 
    case IR_PLAY_ENTER: 
      if (fgIsDvdPlay() && bDom != SV_VTSTT_DOM) 
      // force no repeat mode selection in non-VTSTT domain 
      { 
        vGotoBackMain(); 
        break; 
      } 
      if (_bInputPos == 0xFF)  // just enter by pressing PLAY 
      { 
        _bInputBeg = 0; 
        _bInputPos = bCurRptModeNo; 
        vRedrawGotoReptItem(bRptModeNum); 
        vGotoReptHLItem(TRUE); 
        break; 
      } 
      else  // switch to current repeat setting 
      { 
        if (fgIsDvdPlay()) 
        { 
          vSendUopCmd(UOP_REPEAT, pbReptModeDVD[_bInputPos], 0, 0); 
        } 
        else if (fgIsVcdPlay()) 
        { 
          vSendUopCmd(UOP_REPEAT, pbReptModeVCD[_bInputPos], 0, 0); 
        } 
        vGotoBackMain(); 
        break; 
      } 
  } 
   
  _pvHLFun = vGotoReptHLItem; 
  _pvRedrawFun = vRedrawGotoReptItem; 
  _bTotal = bRptModeNum; 
  vPullDownMenuHandler(); 
} 
 
 
void vDealGotoTimedisp(BYTE fgDeal) large 
{ 
  BYTE bMode = 0 + _rOsdStateCtx.bGotoTimeType; 
  WORD wMsgIdx; 
  BYTE bCntI; 
  WORD pwMsgIdx[4] = { OSD_MSG_TITLE_ELAPSED, 
                       OSD_MSG_TITLE_REMAIN, 
                       OSD_MSG_CHAPTER_ELAPSED, 
                       OSD_MSG_CHAPTER_REMAIN }; 
 
  if (fgIsVcdPlay()) 
  { 
    pwMsgIdx[0] = OSD_MSG_TOTAL_ELAPSED; 
    pwMsgIdx[1] = OSD_MSG_TOTAL_REMAIN; 
    pwMsgIdx[2] = OSD_MSG_SINGLE_ELAPSED; 
    pwMsgIdx[3] = OSD_MSG_SINGLE_REMAIN; 
  } 
 
  wMsgIdx = pwMsgIdx[bMode]; 
     
  if (!fgDeal)  // show current time-display setting 
  { 
    vShowGotoTimedisp(wMsgIdx); 
    return; 
  } 
   
  switch (_bIRKey) 
  { 
    case IR_ENTER: 
    case IR_PLAY: 
    case IR_PLAY_ENTER: 
      if (_bInputPos == 0xFF)  // just enter by pressing PLAY 
      { 
        _bInputBeg = 0; 
        _bInputPos = bMode; 
        vRedrawGotoTimedispItem(4); 
        vGotoTimedispHLItem(TRUE); 
        break; 
      } 
      else  // switch to current time-display setting 
      { 
        _rOsdStateCtx.bGotoTimeType = _bInputPos; 
#ifdef GOTO_STATUS_NO_TTCH 
        if (bSharedInfo(SI_NTSC_PAL) == SV_PAL) 
        { 
          vOsdPosClear(OSD_POS_GOTO_DISP_P); 
        } 
        else 
        { 
          vOsdPosClear(OSD_POS_GOTO_DISP); 
        } 
#endif 
        vUpdateGotoShow(GOTO_SHOW_PANEL_TIME); 
        vGotoBackMain(); 
        break; 
      } 
  } 
   
  _pvHLFun = vGotoTimedispHLItem; 
  _pvRedrawFun = vRedrawGotoTimedispItem; 
  _bTotal = 4; 
  vPullDownMenuHandler(); 
} 
 
 
void vRedrawGotoItem(BYTE fgClear) large 
{ 
  BYTE bCntI; 
  BYTE bCI; 
  WORD wMsgIdx; 
  void (*vFun)(BYTE bYPos) large; 
   
  if (fgClear) 
  { 
    // draw the top green rectangle and paste menu title 
    vSolidRect(_bWBGotoMenu, GOTO_LITEM_X, 0, 
               GOTO_WINDOW_END_X - 17, GOTO_ITEM_BEGIN_Y - 3, 0); 
    vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 4); 
    vOsdPasteMsgXY(GOTO_LITEM_X, 3, 
                   _bWBGotoMenu, OSD_MSG_MENU); 
 
    // clear all pasted messages 
    vSolidRect(_bWBGotoMenu, GOTO_PANEL_WIDTH + 11, GOTO_ITEM_BEGIN_Y - 2, 
               GOTO_WINDOW_END_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 5, 3); 
  } 
 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  for (bCntI = 0; bCntI < GOTO_PAGE_ITEM_NUM; bCntI++) 
  { 
    if (fgClear) 
    { 
      wMsgIdx = _prGotoItem[bCntI + _bGotoBeg].wItemNameMsg; 
      vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bCntI, 
                     _bWBGotoMenu, wMsgIdx); 
    } 
    //if (!fgDrawAll && (bCntI + _bGotoBeg == _bGotoCurItem)) 
    //  continue;  // skip current pointed-to item 
    // using function ptrs in the following block is better, but it will 
    // introduce strange bugs!!!!! 
    vInvokeFun(bCntI + _bGotoBeg, FALSE); 
  } 
 
  vGotoShowUDMark(_bGotoBeg, bGotoTotalItem()); 
} 
 
 
void vGotoHLItem(BYTE fgShow) large 
{ 
  BYTE bYPos = _bGotoCurItem - _bGotoBeg; 
  BYTE bColor; 
  WORD wMsgIdx; 
   
  wMsgIdx = _prGotoItem[_bGotoCurItem].wItemNameMsg; 
     
  if (fgShow) 
    bColor = 5;  // highlight this item 
  else 
    bColor = 3;  // unhighlight this item 
     
  vSolidRect(_bWBGotoMenu, 
             GOTO_LITEM_X - 23, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos, 
             GOTO_RITEM_X - 14, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * (bYPos + 1) - 1, 
             bColor); 
  vSetMsgCol4(_bWBGotoMenu, 0, bColor, 2, 1); 
 
  vOsdPasteMsgXY(GOTO_LITEM_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos, 
                 _bWBGotoMenu, wMsgIdx); 
} 
 
 
// this function will be called in UOP return routines 
void vUpdateGotoShow(BYTE bShowType) large 
{ 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
  BYTE bTtNo = bSharedInfo(fgIsDvdPlay() ? SI_TT_NO : SI_TRACK_NO); 
  BYTE bTtNs = bSharedInfo(fgIsDvdPlay() ? SI_TT_NS : SI_TRACK_NS); 
  BYTE bChNo = bSharedInfo(fgIsDvdPlay() ? SI_CHAP_NO : SI_PTT_NO); 
  BYTE bChNs = bSharedInfo(fgIsDvdPlay() ? SI_CHAP_NS : SI_PTT_NO); 
  BYTE bType = bSharedInfo(SI_DISC_TYPE); 
  BYTE bHour, bMin, bSec; 
  BYTE bBitrate0 = bSharedInfo(SI_V_BITRATE0); 
  BYTE bBitrate1 = bSharedInfo(SI_V_BITRATE1); 
  WORD wBitrate = (bBitrate1 << 8) | bBitrate0; 
  BYTE pbStr[8] = { 7, '0', ':', '0', '0', ':', '0', '0' }; 
  BYTE bPbcState = bSharedInfo(SI_PBC_STATE); 
  BYTE fgShowAll; 
  BYTE bCntI; 
  WORD wMsgIdx; 
 
  if (fgIsDvdPlay() && bDom != SV_VTSTT_DOM) 
  { 
    bTtNo = bChNo = 0; 
  } 
   
  if (bShowType == GOTO_SHOW_PANEL_ALL) 
    fgShowAll = TRUE; 
  else 
    fgShowAll = FALSE; 
   
  if (bShowType == GOTO_SHOW_PANEL_CHAPTER) 
    bShowType = GOTO_SHOW_PANEL_TITLE; 
     
#ifdef GOTO_STATUS_NO_TTCH 
  if (bShowType == GOTO_SHOW_PANEL_ALL || bShowType == GOTO_SHOW_PANEL_TITLE) 
    bShowType = GOTO_SHOW_PANEL_TIME; 
#endif 
 
  switch (bShowType) 
  { 
    case GOTO_SHOW_PANEL_ALL: 
    case GOTO_SHOW_PANEL_TITLE: 
      // show current playing title and chapter 
      pbStr[0] = 4; 
      pbStr[1] = bTtNo / 10 + '0'; 
      pbStr[2] = bTtNo % 10 + '0';  
      pbStr[3] = bChNo / 10 + '0'; 
      pbStr[4] = bChNo % 10 + '0'; 
      if (fgIsDvdPlay()) 
      { 
        wMsgIdx = OSD_MSG_TT_CH_G; 
      } 
      else 
      { 
#ifdef GOTO_VCD_SEGMENT 
        wMsgIdx = OSD_MSG_TK_SG_G; 
#else 
        wMsgIdx = OSD_MSG_TK_G; 
        pbStr[0] = 2; 
#endif 
      } 
      vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 1); 
      if (bSharedInfo(SI_NTSC_PAL) == SV_PAL) 
      { 
        vOsdPosPasteArg(OSD_POS_GOTO_DISP_P, wMsgIdx, pbStr, 0); 
      } 
      else 
      { 
        vOsdPosPasteArg(OSD_POS_GOTO_DISP, wMsgIdx, pbStr, 0); 
      } 
      if (!fgShowAll) 
        break; 
   
    case GOTO_SHOW_PANEL_TIME: 
      // get time info 
      switch (_rOsdStateCtx.bGotoTimeType) 
      { 
        case GOTO_SHOW_TITLE_ELAPSED: 
          bHour = bSharedInfo(SI_TIME_HH); 
          bMin  = bSharedInfo(SI_TIME_MM); 
          bSec  = bSharedInfo(SI_TIME_SS); 
          if (fgIsDvdPlay()) 
            wMsgIdx = OSD_MSG_TITLE_ELAPSED; 
          else 
            wMsgIdx = OSD_MSG_TOTAL_ELAPSED; 
          break; 
 
        case GOTO_SHOW_TITLE_REMAIN: 
          bHour = bSharedInfo(SI_TIME_RMN_HH); 
          bMin  = bSharedInfo(SI_TIME_RMN_MM); 
          bSec  = bSharedInfo(SI_TIME_RMN_SS); 
          if (fgIsDvdPlay()) 
            wMsgIdx = OSD_MSG_TITLE_REMAIN; 
          else 
            wMsgIdx = OSD_MSG_TOTAL_REMAIN; 
          break; 
 
        case GOTO_SHOW_CHAPTER_ELAPSED: 
          bHour = bSharedInfo(SI_TIME_CHAPTER_HH); 
          bMin  = bSharedInfo(SI_TIME_CHAPTER_MM); 
          bSec  = bSharedInfo(SI_TIME_CHAPTER_SS); 
          if (fgIsDvdPlay()) 
            wMsgIdx = OSD_MSG_CHAPTER_ELAPSED; 
          else 
            wMsgIdx = OSD_MSG_SINGLE_ELAPSED; 
          break; 
 
        case GOTO_SHOW_CHAPTER_REMAIN: 
          bHour = bSharedInfo(SI_TIME_CHAPTER_RMN_HH); 
          bMin  = bSharedInfo(SI_TIME_CHAPTER_RMN_MM); 
          bSec  = bSharedInfo(SI_TIME_CHAPTER_RMN_SS); 
          if (fgIsDvdPlay()) 
            wMsgIdx = OSD_MSG_CHAPTER_REMAIN; 
          else 
            wMsgIdx = OSD_MSG_SINGLE_REMAIN; 
          break; 
      } 
      if (BCD2DEC(bMin) >= 60)  // for VCD only, assume max. 99:59 
      { 
        bMin = ((BCD_HI(bMin) - 6) << 4) | BCD_LO(bMin);; 
        bHour++; 
      } 
       
      // show time info 
      vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 1); 
#ifdef GOTO_STATUS_NO_TTCH 
      pbStr[0] = 7; 
      pbStr[1] = bLoByte(wMsgIdx); 
      pbStr[2] = bHiByte(wMsgIdx); 
      pbStr[3] = BCD_LO(bHour) + '0'; 
      pbStr[4] = BCD_HI(bMin) + '0'; 
      pbStr[5] = BCD_LO(bMin) + '0'; 
      pbStr[6] = BCD_HI(bSec) + '0'; 
      pbStr[7] = BCD_LO(bSec) + '0'; 
      if (bSharedInfo(SI_NTSC_PAL) == SV_PAL) 
      { 
        vOsdPosPasteArg(OSD_POS_GOTO_DISP_P, OSD_MSG_TIME_STATUS_G, pbStr, 0); 
      } 
      else 
      { 
        vOsdPosPasteArg(OSD_POS_GOTO_DISP, OSD_MSG_TIME_STATUS_G, pbStr, 0); 
      }       
#else 
      pbStr[0] = 7; 
      pbStr[1] = BCD_LO(bHour) + '0'; 
      pbStr[2] = ':'; 
      pbStr[3] = BCD_HI(bMin) + '0'; 
      pbStr[4] = BCD_LO(bMin) + '0'; 
      pbStr[5] = ':'; 
      pbStr[6] = BCD_HI(bSec) + '0'; 
      pbStr[7] = BCD_LO(bSec) + '0'; 
      vOsdShowStrXY(GOTO_LITEM_X + 308, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 7, 
                    _bWBGotoMenu, pbStr); 
#endif 
       
      if (!fgShowAll) 
        break; 
     
    case GOTO_SHOW_PANEL_BITRATE: 
      // show bitrate info 
      // make VCD's bitrate scale the same as DVD 
      if (fgIsVcdPlay() && wBitrate < 1500) 
      { 
        wBitrate *= (9800.0 / 1499.0); 
      } 
#ifdef GOTO_STATUS_NO_TTCH 
      pbStr[0] = 2; 
      pbStr[1] = (wBitrate / 100) / 10 + '0'; 
      pbStr[2] = (wBitrate / 100) % 10 + '0'; 
      vSetMsgCol4(_bWBGotoMenu, 0, 0, 2, 1); 
      vOsdShowStrXY(GOTO_BITRATE_X, GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 7, 
                    _bWBGotoMenu, pbStr); 
#endif 
      wBitrate *= 1.7; 
      _wStartY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 4 + 7 + 6; 
      _wEndY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * 5 + 7 - 6; 
#ifdef GOTO_STATUS_NO_TTCH 
      _wStartX = GOTO_BITRATE_X + 40; 
#else 
      _wStartX = GOTO_BITRATE_X; 
#endif 
      for (bCntI = 0; bCntI < wBitrate / 1000; bCntI++) 
      { 
        _wStartX += 5; 
        _wEndX = _wStartX; 
        vOsdShowLine(_bWBGotoMenu, 2, 2); 
      } 
      for (; bCntI < 9800.0 * 1.7 / 1000; bCntI++) 
      { 
        _wStartX += 5; 
        _wEndX = _wStartX; 
        vOsdShowLine(_bWBGotoMenu, 0, 2); 
      } 
      break; 
  } 
} 
 
 
void vGotoBackMain(void) large 
{ 
  _bGotoState = STGOTO_MAIN; 
  _bInputPos = 0xFF; 
  _bInputBeg = 0xFF; 
  _bInputNum = 0; 
} 
 
 
// ********************************************************************* 
// Function : void vGotoClose(void) 
// Description :  
// Parameter : None 
// Return    : None 
// ********************************************************************* 
void vGotoClose(void) large 
{ 
  // delete Goto used white board 
   
  //vOsdSetSt(OSD_ST_BURST);  This will cause error(can't delete WB)? 
  //vVoidDis();               This will cause error? 
   
  vDisableWB(_bWBGotoMenu); 
  vDisableWB(_bWBGotoPanel); 
  vDeleteWB(_bWBGotoMenu); 
  vDeleteWB(_bWBGotoPanel); 
   
  //vOsdSetSt(OSD_ST_NML);    This will cause error? 
 
  // hide HL, disable change color 
// megaa downsize begin 
  //vChgColDis(); 
  //vHideHL(HL_1); 
  //vHideHL(HL_2); 
// megaa downsize end 
   
  // get normal wb back 
  vOsdShowWb(OSD_WB_RESTORE); 
 
  vSetExitInputState(); 
} 
 
 
static void v2DigitFieldShower(BYTE bState, BYTE bNo, BYTE bNs) large 
{ 
  BYTE bYPos = bState - _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
  BYTE pbStr[] = { 5, '1', '2', '/', '3', '4' }; 
   
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
 
  if (_bGotoState == bState)  // don't have to update when we are in the state itself 
    return; 
 
  if (fgIsDvdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_DVD_AUDIO: 
      case STGOTO_DVD_SUBTITLE: 
      case STGOTO_DVD_REPEAT: 
      case STGOTO_DVD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
  else if (fgIsVcdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_VCD_REPEAT: 
      case STGOTO_VCD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
 
  pbStr[1] = bNo / 10 + '0'; 
  pbStr[2] = bNo % 10 + '0'; 
  pbStr[4] = bNs / 10 + '0'; 
  pbStr[5] = bNs % 10 + '0'; 
   
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
} 
 
void vShowGotoChapter(void) large 
{ 
  // when VCD, use PTT as the analogy to DVD's chapter 
  BYTE bChNo = bSharedInfo(fgIsDvdPlay() ? SI_CHAP_NO : SI_PTT_NO); 
  BYTE bChNs = bSharedInfo(fgIsDvdPlay() ? SI_CHAP_NS : SI_PTT_NS); 
 
#ifndef GOTO_VCD_SEGMENT 
  if (fgIsVcdPlay()) 
    return; 
#endif 
 
  if (fgIsDvdPlay() && bSharedInfo(SI_DVD_DOM) != SV_VTSTT_DOM) 
    bChNo = bChNs = 0; 
   
  v2DigitFieldShower(STGOTO_DVD_CHAPTER, bChNo, bChNs); 
} 
 
void vShowGotoTitle(void) large 
{ 
  // when VCD, use TRACK as the analogy to DVD's title 
  BYTE bTtNo = bSharedInfo(fgIsDvdPlay() ? SI_TT_NO : SI_TRACK_NO); 
  BYTE bTtNs = bSharedInfo(fgIsDvdPlay() ? SI_TT_NS : SI_TRACK_NS); 
   
  if (fgIsDvdPlay() && bSharedInfo(SI_DVD_DOM) != SV_VTSTT_DOM) 
    bTtNo = 0; 
 
  v2DigitFieldShower(STGOTO_DVD_TITLE, bTtNo, bTtNs); 
} 
 
void vShowGotoAudio(WORD wMsgIdx1, WORD wMsgIdx2, WORD wMsgIdx3) large 
{ 
  BYTE bYPos = STGOTO_DVD_AUDIO - _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
   
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
 
  switch (_bGotoState) 
  { 
    case STGOTO_DVD_AUDIO: 
    case STGOTO_DVD_SUBTITLE: 
    case STGOTO_DVD_REPEAT: 
    case STGOTO_DVD_TIMEDISP: 
      return; 
    default: 
      break; 
  } 
 
  vSolidRect(_bWBGotoMenu, GOTO_RITEM_X, wY, 
             GOTO_MARK_X - 1, wY + LINE_HEIGHT - 1, 3); 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdPasteMsgXY(GOTO_RITEM_X, wY, _bWBGotoMenu, wMsgIdx2); 
  vOsdPasteMsgXY(GOTO_RITEM_X + 80, wY, _bWBGotoMenu, wMsgIdx3); 
} 
 
void vShowGotoSubtitle(WORD wMsgIdx) large 
{ 
  BYTE bYPos = STGOTO_DVD_SUBTITLE - _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
   
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
   
  switch (_bGotoState) 
  { 
    case STGOTO_DVD_AUDIO: 
    case STGOTO_DVD_SUBTITLE: 
    case STGOTO_DVD_REPEAT: 
    case STGOTO_DVD_TIMEDISP: 
      return; 
    default: 
      break; 
  } 
   
  vSolidRect(_bWBGotoMenu, GOTO_RITEM_X, wY, 
             GOTO_MARK_X - 1, wY + LINE_HEIGHT - 1, 3); 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdPasteMsgXY(GOTO_RITEM_X, wY, _bWBGotoMenu, wMsgIdx); 
} 
 
void vShowGotoAngle(void) large 
{ 
  BYTE bAgNo = bSharedInfo(SI_AGL_NO); 
  BYTE bAgNs = bSharedInfo(SI_AGL_NS); 
  BYTE bYPos = STGOTO_DVD_ANGLE - _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
  BYTE pbStr[] = { 3, '1', '/', '3' }; 
   
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
  if (bAgNo > bAgNs) 
    bAgNo = 1; 
 
  switch (_bGotoState) 
  { 
    case STGOTO_DVD_AUDIO: 
    case STGOTO_DVD_SUBTITLE: 
    case STGOTO_DVD_ANGLE: 
    case STGOTO_DVD_REPEAT: 
    case STGOTO_DVD_TIMEDISP: 
      return; 
    default: 
      break; 
  } 
 
  if (bAgNo == 0xFF) 
    bAgNo = 1; 
   
  pbStr[1] = bAgNo + '0'; 
  pbStr[3] = bAgNs + '0'; 
 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
} 
 
static void vTimeFieldShower(BYTE bState, BYTE bHH, BYTE bMM, BYTE bSS) large 
{ 
  BYTE pbStr[] = { 7, '_', ':', '0', '0', ':', '0', '0' }; 
  BYTE bYPos = bState - _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
 
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
 
  if (_bGotoState == bState)  // don't have to update when we are in the state itself 
    return; 
     
  if (fgIsDvdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_DVD_AUDIO: 
      case STGOTO_DVD_SUBTITLE: 
      case STGOTO_DVD_REPEAT: 
      case STGOTO_DVD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
  else if (fgIsVcdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_VCD_REPEAT: 
      case STGOTO_VCD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
   
  if (bHH == 0 && bMM == 0 && bSS == 0) 
  { 
    /* 
    if () 
    { 
      pbStr[2] = pbStr[5] = ' '; 
      vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
    } 
    */ 
    return; 
  } 
 
  if (BCD2DEC(bMM) >= 60)  // for VCD only, assume max 99:59 
  { 
    bMM = ((BCD_HI(bMM) - 6) << 4) | BCD_LO(bMM); 
    bHH++; 
  } 
   
  pbStr[1] = BCD_LO(bHH) + '0'; 
  pbStr[3] = BCD_HI(bMM) + '0'; 
  pbStr[4] = BCD_LO(bMM) + '0'; 
  pbStr[6] = BCD_HI(bSS) + '0'; 
  pbStr[7] = BCD_LO(bSS) + '0'; 
 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdShowStrXY(GOTO_RITEM_X, wY, _bWBGotoMenu, pbStr); 
} 
 
void vShowGotoTime(void) large 
{ 
  BYTE bTotalTimeHH = bSharedInfo(SI_TIME_TOTAL_HH); 
  BYTE bTotalTimeMM = bSharedInfo(SI_TIME_TOTAL_MM); 
  BYTE bTotalTimeSS = bSharedInfo(SI_TIME_TOTAL_SS); 
 
  vTimeFieldShower(fgIsDvdPlay() ? STGOTO_DVD_TIME : STGOTO_VCD_TIME,  
                   bTotalTimeHH, bTotalTimeMM, bTotalTimeSS); 
} 
 
void vShowGotoTimeCH(void) large 
{ 
  BYTE bTotalTimeHH = bSharedInfo(fgIsDvdPlay() ? SI_TIME_TOTAL_CHAPTER_HH : SI_TIME_TOTAL_TRACK_HH); 
  BYTE bTotalTimeMM = bSharedInfo(fgIsDvdPlay() ? SI_TIME_TOTAL_CHAPTER_MM : SI_TIME_TOTAL_TRACK_MM); 
  BYTE bTotalTimeSS = bSharedInfo(fgIsDvdPlay() ? SI_TIME_TOTAL_CHAPTER_SS : SI_TIME_TOTAL_TRACK_SS); 
 
  vTimeFieldShower(fgIsDvdPlay() ? STGOTO_DVD_TIME_CH : STGOTO_VCD_TIME_CH,  
                   bTotalTimeHH, bTotalTimeMM, bTotalTimeSS); 
} 
 
void vShowGotoRepeat(WORD wMsgIdx) large 
{ 
  BYTE bYPos = (fgIsDvdPlay() ? STGOTO_DVD_REPEAT : STGOTO_VCD_REPEAT ) - 
                _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
 
 
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
   
  if (fgIsDvdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_DVD_AUDIO: 
      case STGOTO_DVD_SUBTITLE: 
      case STGOTO_DVD_REPEAT: 
      case STGOTO_DVD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
  else if (fgIsVcdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_VCD_REPEAT: 
      case STGOTO_VCD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
 
  vSolidRect(_bWBGotoMenu, GOTO_RITEM_X, wY, 
             GOTO_MARK_X - 1, wY + LINE_HEIGHT - 1, 3); 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdPasteMsgXY(GOTO_RITEM_X, wY, _bWBGotoMenu, wMsgIdx); 
} 
 
 
void vShowGotoTimedisp(WORD wMsgIdx) large 
{ 
  BYTE bYPos = (fgIsDvdPlay() ? STGOTO_DVD_TIMEDISP : STGOTO_VCD_TIMEDISP) - 
                _bGotoBeg; 
  WORD wY = GOTO_ITEM_BEGIN_Y + LINE_HEIGHT * bYPos; 
 
  if (bYPos < 0 || bYPos >= GOTO_PAGE_ITEM_NUM)  // out of display range 
    return; 
   
  if (fgIsDvdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_DVD_AUDIO: 
      case STGOTO_DVD_SUBTITLE: 
      case STGOTO_DVD_REPEAT: 
      case STGOTO_DVD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
  else if (fgIsVcdPlay()) 
  { 
    switch (_bGotoState) 
    { 
      case STGOTO_VCD_REPEAT: 
      case STGOTO_VCD_TIMEDISP: 
        return; 
      default: 
        break; 
    } 
  } 
   
  vSolidRect(_bWBGotoMenu, GOTO_RITEM_X, wY, 
             GOTO_MARK_X - 1, wY + LINE_HEIGHT - 1, 3); 
  vSetMsgCol4(_bWBGotoMenu, 0, 3, 2, 1); 
  vOsdPasteMsgXY(GOTO_RITEM_X, wY, _bWBGotoMenu, wMsgIdx); 
} 
 
void vShowGotoPbc(WORD wMsgIdx) large 
{ 
  if (bSharedInfo(SI_V_4_3) == SV_V_16_9) 
  { 
    vSolidRect(_bWBGotoPanel, 18, 60, 88, 60 + LINE_HEIGHT - 1, 1); 
  } 
  else 
  { 
    vSolidRect(_bWBGotoPanel, 76, 60, 150, 60 + LINE_HEIGHT - 1, 1); 
  } 
   
  if (wMsgIdx != OSD_MSG_NULL) 
  { 
    vSetMsgCol4(_bWBGotoPanel, 0, 1, 1, 2); 
    if (bSharedInfo(SI_V_4_3) == SV_V_16_9) 
    { 
      vOsdPasteMsgXY(18, 60, _bWBGotoPanel, wMsgIdx); 
    } 
    else 
    { 
      vOsdPasteMsgXY(76, 60, _bWBGotoPanel, wMsgIdx); 
    } 
  } 
} 
 
// using function ptrs is better 
void vInvokeFun(BYTE bState, BYTE fgDeal) large 
{ 
  if (fgIsDvdPlay()) 
  { 
    switch (bState) 
    { 
      case STGOTO_DVD_CHAPTER: 
        vDealGotoChapter(fgDeal); 
        break; 
      case STGOTO_DVD_TITLE: 
        vDealGotoTitle(fgDeal); 
        break; 
      case STGOTO_DVD_AUDIO: 
        vDealGotoAudio(fgDeal); 
        break; 
      case STGOTO_DVD_SUBTITLE: 
        vDealGotoSubtitle(fgDeal); 
        break; 
      case STGOTO_DVD_ANGLE: 
        vDealGotoAngle(fgDeal); 
        break; 
      case STGOTO_DVD_TIME: 
        vDealGotoTime(fgDeal); 
        break; 
      case STGOTO_DVD_TIME_CH: 
        vDealGotoTimeCH(fgDeal); 
        break; 
      case STGOTO_DVD_REPEAT: 
        vDealGotoRepeat(fgDeal); 
        break; 
      case STGOTO_DVD_TIMEDISP: 
        vDealGotoTimedisp(fgDeal); 
        break; 
    } 
  } 
  else if (fgIsVcdPlay()) 
  { 
    switch (bState) 
    { 
      case STGOTO_VCD_CHAPTER: 
        vDealGotoChapter(fgDeal); 
        break; 
      case STGOTO_VCD_TITLE: 
        vDealGotoTitle(fgDeal); 
        break; 
      case STGOTO_VCD_TIME: 
        vDealGotoTime(fgDeal); 
        break; 
      case STGOTO_VCD_TIME_CH: 
        vDealGotoTimeCH(fgDeal); 
        break; 
      case STGOTO_VCD_REPEAT: 
        vDealGotoRepeat(fgDeal); 
        break; 
      case STGOTO_VCD_TIMEDISP: 
        vDealGotoTimedisp(fgDeal); 
        break; 
    } 
  } 
} 
 
#ifndef PLAYER_FLMENU 
  #ifdef DDISC_FTYPE_JPEG_SUPPORT 
  extern void vFlChgLang(BYTE bLang) large; 
  #endif 
#endif 
 
void vGotoOsdLangKey(void) large 
{ 
  BYTE bLang = bEepromReadByte(OSD_LANG_POSITION); 
 
  if (bLang >= EV_OSD_LANG_NS - 1) 
  { 
    bLang = 0; 
  } 
  else 
  { 
    bLang++; 
  } 
 
  vOsdSetLang(bLang); 
#if (!defined(PLAYER_FLMENU) && defined(SUPPORT_DATA_DISC)) 
  #ifdef DDISC_FTYPE_JPEG_SUPPORT 
    vFsMenuChangeLang(bLang); 
  #endif 
#endif 
 
  //vOsdPosShow(OSD_POS_NORMAL, pwSetOsdLan[bLang], OSD_TIMEOUT_SHORT); 
  fgEepromWriteByte(OSD_LANG_POSITION, bLang); 
} 
 
BOOL fgChkGotoExit(void) large 
{ 
  BYTE bDom = bSharedInfo(SI_DVD_DOM); 
  BYTE bPbcState = bSharedInfo(SI_PBC_STATE); 
  BYTE bHliState = bSharedInfo(SI_HLI_STATE); 
  BYTE bTrkNo = bSharedInfo(SI_TRACK_NO); 
 
  if (!fgIsInGoto()) 
  { 
    return (FALSE); 
  } 
     
  if (((fgIsDvdPlay() && bDom != SV_VTSTT_DOM) || bPbcState == SV_STOP || bHliState == 0) || 
      (fgIsVcdPlay() && bTrkNo == 0)) 
  { 
    return (TRUE); 
  } 
 
  return (FALSE); 
} 
 
// ********************************************************************* 
// Function : void vGotoEnter(void) 
// Description : 
// Parameter : None 
// Return    : None 
// ********************************************************************* 
void vGotoEnter(void) large 
{ 
  // if OSD command queue full, not allow enter GOTO menu 
  if (bSharedInfo(SI_OSD_CMD_BUF_FULL) == TRUE) 
  { 
    return; 
  } 
   
  vGotoInitState(); 
} 
 
// ********************************************************************* 
// Function : void vGotoExit(void) 
// Description : 
// Parameter : None 
// Return    : None 
// ********************************************************************* 
void vGotoExit(void) large 
{ 
  _rOsdStateCtx.fgGotoShow = FALSE; 
} 
 
#else /* PLAYER_GOTO */ 
 
static code BYTE pbGotoSeg[1] = { 0 }; 
 
void vGotoDummy(void) large 
{ 
  BYTE bTmp = pbGotoSeg[0]; 
} 
 
#endif /* PLAYER_GOTO */