Changeset 120


Ignore:
Timestamp:
Oct 7, 2023, 11:26:26 PM (22 months ago)
Author:
erdmann
Message:

attempt to fix Netlabs ticket #19

Location:
branches/v2.9_Lars/mediafolder
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/v2.9_Lars/mediafolder/c/m3ufolder/m3ufolderoverriddenwpmethods.cpp

    r2 r120  
    11/*
    22 * This file is (C) Chris Wohlgemuth 2002-2003
    3  * 
     3 *
    44 * It's part of the Media-Folder distribution
    55 */
     
    3232extern ULONG ulQWL_RIGHTCTRLHWND;
    3333extern ULONG ulQWL_LEFTCTRLHWND;
    34 
    35 #if 0
    36 /* For calling the method in the MMAudio class. Linking to the DLL would require the
    37    new audio classes. By dynamically querying the method the media folder works without
    38    installing the audio classes. */ 
    39 typedef ULONG   SOMLINK somTP_MMCDTrack_cwmmQueryTrackInfo(MMCDTrack *somSelf,
    40                 char** chrString,
    41                 ULONG ulSize,
    42                 int iWhich);
    43 typedef somTP_MMCDTrack_cwmmQueryTrackInfo *somTD_MMCDTrack_cwmmQueryTrackInfo;
    44 extern somTD_MMCDTrack_cwmmQueryTrackInfo methodPtrCDTrack;
    45 #endif
    4634
    4735extern LOADEDBITMAP allBMPs[];
     
    8876  ULONG ulSize;
    8977
    90   thisPtr=(CWM3UFolder*)arg;   
     78  thisPtr=(CWM3UFolder*)arg;
    9179  if(!somIsObj(thisPtr))
    9280    return;
     
    9886  if(!chrFileName)
    9987    return;
    100  
     88
    10189  chrFolderName=chrFileName+CCHMAXPATH+1;
    10290  chrRexxScript=chrFolderName+CCHMAXPATH+1;
     
    10593  if(!((WPFileSystem*)thisPtr->wpObjM3UFile)->wpQueryRealName(chrFileName, &ulSize, TRUE))
    10694    return;
    107  
     95
    10896  ulSize=CCHMAXPATH;
    10997  if(!thisPtr->wpQueryRealName(chrFolderName, &ulSize, TRUE))
     
    113101  if(hab) {
    114102    hmq=WinCreateMsgQueue(hab,0);
    115     if(hmq) {     
     103    if(hmq) {
    116104      RXSTRING arg[2];                    /* argument string for REXX  */
    117105      RXSTRING rexxretval;                /* return value from REXX    */
    118106      APIRET   rc;                        /* return code from REXX     */
    119107      SHORT    rexxrc = 0;                /* return code from function */
    120      
    121      
     108
     109
    122110      sprintf(chrRexxScript,"%s%s",  chrInstallDir,RX_INSERT_PLAYLISTTRACKS);
    123111      //HlpWriteToTrapLog("chrRexxScript: %s\n", chrRexxScript);
     
    126114      /* We could provide a buffer for the interpreter to use instead. */
    127115      rexxretval.strlength = 0L;          /* initialize return to empty*/
    128      
     116
    129117      MAKERXSTRING(arg[0], chrFileName, strlen(chrFileName));/* create input argument     */
    130       MAKERXSTRING(arg[1], chrFolderName, strlen(chrFolderName));/* create input argument     */             
    131      
     118      MAKERXSTRING(arg[1], chrFolderName, strlen(chrFolderName));/* create input argument     */
     119
    132120      TRY_LOUD(RX_START) {
    133121        /* Here we call the interpreter.  We don't really need to use    */
     
    144132                     (PSHORT)     &rexxrc,       /* Rexx program output   */
    145133                     (PRXSTRING)  &rexxretval ); /* Rexx program output   */
    146        
     134
    147135        if(rc) {
    148           sprintf(chrFileName,"Error in the Rexx skript %s\n\n Get more information with 'help REX%04d'.\n", 
     136          sprintf(chrFileName,"Error in the Rexx skript %s\n\n Get more information with 'help REX%04d'.\n",
    149137                  "", rc*-1);
    150138          WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, chrFileName, "", 1234, MB_OK|MB_MOVEABLE|MB_ERROR);
    151139        }
    152         DosFreeMem(rexxretval.strptr);          /* Release storage given to us by REXX.  */     
     140        DosFreeMem(rexxretval.strptr);          /* Release storage given to us by REXX.  */
    153141      }
    154142      CATCH(RX_START)
    155143        {}END_CATCH;
    156                
     144
    157145        WinDestroyMsgQueue(hmq);
    158146    }
     
    160148  }
    161149  thisPtr->fContentsChanged=FALSE;
    162   thisPtr->wpFreeMem((PBYTE)chrFileName); 
     150  thisPtr->wpFreeMem((PBYTE)chrFileName);
    163151}
    164152
     
    203191/*                                                   */
    204192/*****************************************************/
    205 MRESULT EXPENTRY m3uFldrContainerProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 
     193MRESULT EXPENTRY m3uFldrContainerProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    206194{
    207195  CWMediaFolder* thisPtr;
     
    272260/*                                                                          */
    273261/****************************************************************************/
    274 MRESULT EXPENTRY m3uTopCtrlDialogProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 
    275 {
    276    
     262MRESULT EXPENTRY m3uTopCtrlDialogProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     263{
     264
    277265  switch(msg)
    278266    {
     
    284272        ULONG ulStyle;
    285273        SWP swp;
    286        
     274
    287275        WinSetWindowULong(hwnd,QWL_USER,(ULONG)PVOIDFROMMP(mp2));//Save object ptr.
    288276        WinQueryWindowPos(WinQueryWindow(hwnd,QW_PARENT),&swp);
     
    299287      WinSetFocus(HWND_DESKTOP, WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),FID_CLIENT));
    300288      return WinSendMsg(WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),FID_CLIENT),msg,mp1,mp2);
    301      
     289
    302290      /*****************************************************/
    303291      /* Paint the background.                             */
     
    321309          ptl.x=lTemp*rclSource.xRight;
    322310          lTemp=rcl.yBottom/rclSource.yTop;
    323           lTemp*=rclSource.yTop;   
     311          lTemp*=rclSource.yTop;
    324312          while(ptl.x<rcl.xRight) {
    325313            ptl.y=lTemp;
    326314            while(ptl.y<rcl.yTop) {/* y direction */
    327315              WinDrawBitmap(hps, allBMPs[CTRLIDX_BOTTOM].hbm,
    328                             &rclSource, 
     316                            &rclSource,
    329317                            (PPOINTL)&ptl,
    330318                            0, 0,
     
    332320              ptl.y+=allBMPs[CTRLIDX_BOTTOM].bmpInfoHdr.cy;
    333321            };
    334             ptl.x+=allBMPs[CTRLIDX_BOTTOM].bmpInfoHdr.cx; 
     322            ptl.x+=allBMPs[CTRLIDX_BOTTOM].bmpInfoHdr.cx;
    335323          };
    336324          WinEndPaint(hps);
     
    351339        rclSource.xRight=allBMPs[CTRLIDX_TOPLEFT].bmpInfoHdr.cx;
    352340        WinDrawBitmap(hps, allBMPs[CTRLIDX_TOPLEFT].hbm,
    353                       &rclSource, 
     341                      &rclSource,
    354342                      (PPOINTL)&rclSave,
    355343                      0, 0,
     
    364352        rclSource.xRight=allBMPs[CTRLIDX_TOPRIGHT].bmpInfoHdr.cx;
    365353        WinDrawBitmap(hps, allBMPs[CTRLIDX_TOPRIGHT].hbm,
    366                       &rclSource, 
     354                      &rclSource,
    367355                      (PPOINTL)&rclSave,
    368356                      0, 0,
     
    386374 *                                                          *
    387375************************************************************/
    388 MRESULT EXPENTRY m3uFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 
     376MRESULT EXPENTRY m3uFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    389377{
    390378  CWM3UFolder* thisPtr;
     
    419407#endif
    420408              case 0x2d1: /* View menu */
    421                 /* Remove change to Tree from menubar menu */ 
     409                /* Remove change to Tree from menubar menu */
    422410                WinSendMsg(HWNDFROMMP(mp2),MM_REMOVEITEM,MPFROM2SHORT(717,TRUE),0);
    423411                /* Icon view */
     
    462450          case ID_MENUITEMEXIT:
    463451            WinPostMsg(hwnd, WM_CLOSE, 0, 0);
    464             return MRFALSE; 
     452            return MRFALSE;
    465453          case ID_MENUITEMSAVE:
    466454            {
     
    472460                  }
    473461                }
    474               return MRFALSE; 
     462              return MRFALSE;
    475463            }
    476464          default:
    477             if(SHORT1FROMMP(mp1)>=FIRSTUSERITEM) { 
     465            if(SHORT1FROMMP(mp1)>=FIRSTUSERITEM) {
    478466              BOOL bHandled=FALSE;
    479              
     467
    480468              TRY_LOUD(AF_MENU) {
    481469#if 0
     
    484472                    thisPtr=(CWMediaFolder*) WinQueryWindowULong(hwndDialog,QWL_USER);
    485473                    if(somIsObj(thisPtr)) {
    486                      
     474
    487475                      CWMenuFolder * wpFolder; 
    488476                      HOBJECT hObject;
     
    490478                      somTD_CWMenuFolder_mfCheckSkriptMenuItems methodPtr;
    491479                      M_WPObject *m_wpObject;
    492                      
     480
    493481                      if(!bHandled)
    494482                        bHandled=thisPtr->cwCheckUserMenuItems(USERMENUFOLDER_MEDIAFOLDER , SHORT1FROMMP(mp1));
     
    557545
    558546  /* Reregister wpFolder window class on first opening */
    559   /* We need this private code to have some private 
     547  /* We need this private code to have some private
    560548     window words */
    561549  if(!g_fRegisteredWindowClass)
    562550    {
    563551      CLASSINFO ci;
    564      
     552
    565553      if(WinQueryClassInfo(WinQueryAnchorBlock(HWND_DESKTOP),
    566554                           (PSZ)"wpFolder window",
     
    589577  /* Skip media folder. Because of this skip we had to register the window words here (see above).
    590578     It's not asured a Mediafolder was already opended. Normaly the window words are added in
    591      wpOpen() of the Mediafolder. 
     579     wpOpen() of the Mediafolder.
    592580     FIXME: This only works if CWProgFolder->CWMediaFolder->CWM3UFolder is the class hierarchy */
    593581  hwnd=CWProgFolder::wpOpen(hwndCnr, ulView, ulParam);
    594582
    595583  /* Only subclass folder frames, not settings notebooks */
    596   if(ulView!=OPEN_SETTINGS){   
     584  if(ulView!=OPEN_SETTINGS){
    597585    if(!hResource) {
    598586      errorResource();
     
    624612        /* Menu bar found */
    625613
    626         /* Remove folder item from menubar menu */ 
     614        /* Remove folder item from menubar menu */
    627615        WinSendMsg( myFrameCtrlHWND, MM_REMOVEITEM, MPFROM2SHORT(0x2cf,TRUE),0);
    628616
     
    633621        mi.afStyle=MIS_TEXT|MIS_SUBMENU;
    634622        mi.id=ID_MENUFILE;
    635         mi.afAttribute=NULL;               
     623        mi.afAttribute=NULL;
    636624        mi.hwndSubMenu=hwndMenu;
    637625        mi.hItem=NULL;
     
    640628        getMessage(text, IDSTR_MENUFILE,sizeof(text), hResource, hwnd);
    641629        WinSendMsg(myFrameCtrlHWND,MM_INSERTITEM,MPFROMP(&mi),
    642                    (MPARAM)text); 
     630                   (MPARAM)text);
    643631
    644632        /* Insert skript and user menu item if necessary */
     
    675663            iItemCount=(int)WinSendMsg(myFrameCtrlHWND,MM_QUERYITEMCOUNT,(MPARAM)0,
    676664                                       (MPARAM)0);
    677            
     665
    678666            /* Fill the MENUITEM structure */
    679667            mi.iPosition=iItemCount-1;
    680668            mi.afStyle=MIS_TEXT|MIS_SUBMENU;
    681669            mi.id=ID_MBMENUSKRIPTS;
    682             mi.afAttribute=NULL;               
     670            mi.afAttribute=NULL;
    683671            mi.hwndSubMenu=hwndMenu;
    684672            mi.hItem=NULL;
     
    687675            getMessage(text, IDSTR_MENUSKRIPTS,sizeof(text), hResource, hwnd);
    688676            WinSendMsg(myFrameCtrlHWND,MM_INSERTITEM,MPFROMP(&mi),
    689                        (MPARAM)text); 
     677                       (MPARAM)text);
    690678          }/* end of if(hwndMenu) */
    691679        }
     
    700688         the procedure saves this pointer for later use. */
    701689      myFrameCtrlHWND=WinLoadDlg(hwnd,hwnd, m3uTopCtrlDialogProc,hResource,IDDLG_TOPFRAME ,this);
    702       /* Save the HWND in the instance data */   
     690      /* Save the HWND in the instance data */
    703691      //      hwndTop=myFrameCtrlHWND;
    704       /* Save the HWND in the Window words */   
    705       WinSetWindowULong( hwnd, ulQWL_TOPCTRLHWND, myFrameCtrlHWND); 
    706    
     692      /* Save the HWND in the Window words */
     693      WinSetWindowULong( hwnd, ulQWL_TOPCTRLHWND, myFrameCtrlHWND);
     694
    707695      if(myFrameCtrlHWND){
    708696        /* Query the size of the dialog */
     
    712700        //        sizel.cy=rectl.yTop-rectl.yBottom;
    713701        sizel.cy=12;
    714         /* Call a method of CWProgFolder to add the dialog as a framecontrol. 
     702        /* Call a method of CWProgFolder to add the dialog as a framecontrol.
    715703           FCTL_TOP means put it at the top of the folder.
    716704           After calling cwUpdateFrame(hwnd) it will be visible */
     
    722710         the procedure saves this pointer for later use. */
    723711      myFrameCtrlHWND=WinLoadDlg(hwnd,hwnd,leftCtrlDialogProc,hResource,IDDLG_LEFTFRAME ,this);
    724       /* Save the HWND in the instance data */   
     712      /* Save the HWND in the instance data */
    725713      //    hwndLeft=myFrameCtrlHWND;
    726       /* Save the HWND in the Window words */   
     714      /* Save the HWND in the Window words */
    727715      WinSetWindowULong( hwnd, ulQWL_LEFTCTRLHWND, myFrameCtrlHWND);
    728        
    729    
     716
     717
    730718      if(myFrameCtrlHWND){
    731719        /* Query the size of the dialog */
     
    734722        sizel.cx=allBMPs[CTRLIDX_TOPRIGHT].bmpInfoHdr.cx-1-7-2;//rectl.xRight-rectl.xLeft;
    735723        //  sizel.cx=rectl.xRight-rectl.xLeft;
    736         /* Call a method of CWProgFolder to add the dialog as a framecontrol. 
     724        /* Call a method of CWProgFolder to add the dialog as a framecontrol.
    737725           FCTL_RIGHT means put it at the RIGHT of the folder.
    738726           After calling cwUpdateFrame(hwnd) it will be visible */
     
    744732         the procedure saves this pointer for later use. */
    745733      myFrameCtrlHWND=WinLoadDlg(hwnd,hwnd,rightCtrlDialogProc,hResource,IDDLG_FRAMERIGHT ,this);
    746       /* Save the HWND in the instance data */   
     734      /* Save the HWND in the instance data */
    747735      //      hwndRight=myFrameCtrlHWND;
    748       /* Save the HWND in the Window words */   
     736      /* Save the HWND in the Window words */
    749737      WinSetWindowULong( hwnd, ulQWL_RIGHTCTRLHWND, myFrameCtrlHWND);
    750      
     738
    751739      if(myFrameCtrlHWND){
    752740        CNRINFO cnrInfo;
    753         HWND hwndContainer; 
     741        HWND hwndContainer;
    754742        PVIEWITEM pView;
    755743
     
    758746        /* It's the right dialog so we need the width but not the height. */
    759747        sizel.cx=allBMPs[CTRLIDX_TOPRIGHT].bmpInfoHdr.cx-1-7-2;// rectl.xRight-rectl.xLeft;
    760         /* Call a method of CWProgFolder to add the dialog as a framecontrol. 
     748        /* Call a method of CWProgFolder to add the dialog as a framecontrol.
    761749           FCTL_RIGHT means put it at the RIGHT of the folder.
    762750           After calling cwUpdateFrame(hwnd) it will be visible */
    763751        cwAddFrameCtl(hwnd, myFrameCtrlHWND, sizel, FCTL_RIGHT, FCTL_POSABOVE|FCTL_POSBELOW);
    764        
     752
    765753        //        hwndContainer=WinWindowFromID(myFrameCtrlHWND, IDCNR_PLAYLIST);
    766754        //  WinSendMsg(hwndContainer,CM_QUERYCNRINFO, MPFROMP(&cnrInfo),
     
    772760         the procedure saves this pointer for later use. */
    773761      myFrameCtrlHWND=WinLoadDlg(hwnd,hwnd,bottomCtrlDialogProc,hResource,IDDLG_BOTTOMFRAME ,this);
    774       /* Save the HWND in the instance data */   
    775       hwndBottom=myFrameCtrlHWND;           
    776       /* Save the HWND in the Window words */   
     762      /* Save the HWND in the instance data */
     763      hwndBottom=myFrameCtrlHWND;
     764      /* Save the HWND in the Window words */
    777765      WinSetWindowULong( hwnd, ulQWL_BOTTOMCTRLHWND, myFrameCtrlHWND);
    778766
     
    783771        sizel.cy=rectl.yTop-rectl.yBottom-2;
    784772        //    sizel.cy=allBMPs[MAIN_BMP_IDX].bmpInfoHdr.cy;
    785         /* Call a method of CWProgFolder to add the dialog as a framecontrol. 
     773        /* Call a method of CWProgFolder to add the dialog as a framecontrol.
    786774           FCTL_TOP means put it at the top of the folder.
    787775           After calling cwUpdateFrame(hwnd) it will be visible */
     
    810798        SysWriteToTrapLog("\nTrap occured in %s, file: %s above line %d.\n",
    811799                          __FUNCTION__, __FILE__, __LINE__);
    812        
    813       } END_CATCH;   
     800
     801      } END_CATCH;
    814802
    815803      /* Make sure on open the container is visible */
     
    827815}
    828816
    829 MRESULT CWM3UFolder::wpDrop(HWND hwndCnr,PDRAGINFO pDragInfo,PDRAGITEM pDragItem)
    830 {
    831   return CWMediaFolder::wpDrop(hwndCnr, pDragInfo, pDragItem);
     817MRESULT CWM3UFolder::wpDragOver(HWND hwndCnr,PDRAGINFO pDragInfo)
     818{
     819  ULONG ulNumberOfObjects;
     820  WPObject *wpObject = NULL; 
     821  USHORT usIndicator=DOR_NEVERDROP,usOp=0;
     822
     823  /* Get access to the dragInfo */
     824  if (DrgAccessDraginfo(pDragInfo)) {
     825      PDRAGITEM pDragItem = NULL;
     826      M_CWMediaFolder *mediaFolderClass = NULL;
     827
     828        /* Get number of items */
     829        ulNumberOfObjects = DrgQueryDragitemCount( pDragInfo);
     830
     831        if(ulNumberOfObjects>1) {
     832         usIndicator = DOR_NODROP;
     833         usOp = 0;
     834         goto quit;
     835        }
     836
     837      /* check if a WPS object was dropped, we do not accept anything else */
     838      pDragItem = DrgQueryDragitemPtr(pDragInfo,0);
     839      if (!DrgVerifyRMF(pDragItem,"DRM_OBJECT","DRF_OBJECT")) {
     840         usIndicator = DOR_NEVERDROP;
     841         usOp = 0;
     842         goto quit;
     843      } /* endif */
     844
     845      /*
     846         refuse drop if WPS object pointer is not valid or if the object is
     847         a descendant of MMCDTrack class (see Netlabs ticket #19)
     848      */
     849      wpObject = (WPObject *)OBJECT_FROM_PREC(pDragItem->ulItemID);
     850      mediaFolderClass = (M_CWMediaFolder *)CWMediaFolder::__ClassObject;
     851      if (!somIsObj(wpObject) || wpObject->somIsA(mediaFolderClass->MMCDTrackClass)) {
     852         usIndicator = DOR_NEVERDROP;
     853         usOp = 0;
     854         goto quit;
     855      } /* endif */
     856
     857        switch(pDragInfo->usOperation)
     858       {
     859       case DO_DEFAULT:
     860       case DO_LINK:
     861         usIndicator = DOR_DROP;
     862         usOp = DO_LINK;
     863         break;
     864      default:
     865         usIndicator = DOR_NODROPOP;
     866         usOp = DO_LINK;
     867         break;
     868       }
     869quit:
     870     /* Free the draginfo */
     871     DrgFreeDraginfo(pDragInfo);
     872  }
     873  return MRFROM2SHORT(usIndicator,usOp);
    832874}
    833875
     
    847889    return;
    848890
    849   thisPtr=(CWM3UFolder*)parms->thisPtr;   
     891  thisPtr=(CWM3UFolder*)parms->thisPtr;
    850892  if(!somIsObj(thisPtr))
    851893    return;
     
    862904    hmq=WinCreateMsgQueue(hab,0);
    863905    if(hmq) {
    864       FILE* fStream;     
     906      FILE* fStream;
    865907
    866908      if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP), parms->hwndCnr))
     
    894936                    else
    895937                      break;/* Error */
    896                                        
     938
    897939                    /* Get the name of the audio file */
    898940                    ulSize=sizeof(chrFileName);
     
    906948                  break;
    907949                }/* for() */
    908             }/* fopen() */   
     950            }/* fopen() */
    909951          fclose(fStream);
    910952        }
     
    918960    /* Close and destroy the folder if requested */
    919961    WinPostMsg(parms->hwndFrame, WM_CLOSE, 0, 0);
    920     if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP), thisPtr->hwndObject)) 
     962    if(WinIsWindow(WinQueryAnchorBlock(HWND_DESKTOP), thisPtr->hwndObject))
    921963      WinPostMsg(thisPtr->hwndObject, WM_APPTERMINATENOTIFY, 0, 0);
    922964  }
     
    9681010                           title, IDSTR_CLOSETITLE, sizeof(title),
    9691011                           queryResModuleHandle(),
    970                            HWND_DESKTOP, 
     1012                           HWND_DESKTOP,
    9711013                           MB_YESNOCANCEL|MB_MOVEABLE|MB_ICONQUESTION))==MBID_CANCEL)
    9721014      return FALSE;
  • branches/v2.9_Lars/mediafolder/include/m3ufolder.hh

    r51 r120  
    2828  HWND hwndFrame;
    2929  BOOL fSaveOnly;
    30 }M3UTHREADPARMS; 
     30}M3UTHREADPARMS;
    3131
    3232#pragma SOMAsDefault(on)
     
    4848  virtual BOOL wpclsQueryDefaultHelp(PULONG HelpPanelId,PSZ HelpLibrary);
    4949  virtual BOOL wpclsCreateDefaultTemplates(WPObject * wpObject);
    50   /* 
     50  /*
    5151  virtual void wpclsUnInitData();
    5252
     
    7676  virtual ULONG wpFilterPopupMenu(ULONG ulFlags, HWND hwndCnr, BOOL fMultiSelect);
    7777  virtual BOOL wpModifyPopupMenu(HWND hwndMenu, HWND hwndCnr, ULONG ulPosition);
    78   virtual MRESULT wpDrop(HWND hwndCnr,PDRAGINFO pDragInfo,PDRAGITEM pDragItem); 
     78  virtual MRESULT wpDragOver(HWND hwndCnr,PDRAGINFO pDragInfo);
    7979#if 0
    8080  virtual BOOL wpRestoreState(ULONG ulReserved);
Note: See TracChangeset for help on using the changeset viewer.