1 /*
2  * DesktopPowerpointViewer.cpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #include <iostream>
17 
18 #include <windows.h>
19 #include <winuser.h>
20 #include <oleauto.h>
21 
22 #include <shared_core/Error.hpp>
23 #include <core/system/System.hpp>
24 
25 #include "DesktopComUtils.hpp"
26 #include "DesktopPowerpointViewer.hpp"
27 
28 using namespace rstudio::core;
29 
30 namespace rstudio {
31 namespace desktop {
32 
PowerpointViewer()33 PowerpointViewer::PowerpointViewer():
34     OfficeViewer(L"Powerpoint.Application", L"Presentations",
35                  1 /* position of read-only flag in Open method */),
36     slideIndex_(0)
37 {
38 }
39 
getDocumentWindow(IDispatch * source,IDispatch ** window) const40 Error PowerpointViewer::getDocumentWindow(IDispatch* source, IDispatch** window) const
41 {
42    Error errorHR = Success();
43    HRESULT hr = S_OK;
44 
45    // Get the first document window for the presentation
46    IDispatch* idispWindows = nullptr;
47    VARIANT varResult;
48    VARIANT varItem;
49    varItem.vt = VT_INT;
50    varItem.intVal = 1;
51    VERIFY_HRESULT(getIDispatchProp(source, L"Windows", &idispWindows));
52    VERIFY_HRESULT(invokeDispatch(DISPATCH_METHOD, &varResult, idispWindows, L"Item", 1, varItem));
53    *window = varResult.pdispVal;
54 
55 LErrExit:
56    return errorHR;
57 }
58 
savePosition(IDispatch * source)59 Error PowerpointViewer::savePosition(IDispatch* source)
60 {
61    Error errorHR = Success();
62    HRESULT hr = S_OK;
63 
64    IDispatch* idispPres      = nullptr;
65    IDispatch* idispSelection = nullptr;
66    IDispatch* idispRange     = nullptr;
67 
68    // Get the window containing the document interface
69    errorHR = getDocumentWindow(source, &idispPres);
70    if (errorHR)
71       return errorHR;
72 
73    // Get the selection (the slides the user has selected)
74    VERIFY_HRESULT(getIDispatchProp(idispPres, L"Selection", &idispSelection));
75    VERIFY_HRESULT(getIDispatchProp(idispSelection, L"SlideRange", &idispRange));
76 
77    // Find the slide number the user's working on
78    VERIFY_HRESULT(getIntProp(idispRange, L"SlideNumber", &slideIndex_));
79 
80 LErrExit:
81    return errorHR;
82 }
83 
restorePosition(IDispatch * target) const84 Error PowerpointViewer::restorePosition(IDispatch* target) const
85 {
86    Error errorHR = Success();
87    HRESULT hr = S_OK;
88 
89    IDispatch* idispPres = nullptr;
90    IDispatch* idispView = nullptr;
91 
92    // Get the window containing the document interface
93    errorHR = getDocumentWindow(target, &idispPres);
94    if (errorHR)
95       return errorHR;
96 
97    // Get the slide view
98    VERIFY_HRESULT(getIDispatchProp(idispPres, L"View", &idispView));
99 
100    // Go to the slide in question
101    VARIANT varSlide;
102    varSlide.vt = VT_INT;
103    varSlide.intVal = slideIndex_;
104    VERIFY_HRESULT(invokeDispatch(DISPATCH_METHOD, nullptr, idispView,
105                                  L"GotoSlide", 1, varSlide));
106 
107 LErrExit:
108    return errorHR;
109 }
110 
resetPosition()111 void PowerpointViewer::resetPosition()
112 {
113    slideIndex_ = 0;
114 }
115 
hasPosition() const116 bool PowerpointViewer::hasPosition() const
117 {
118    return slideIndex_ > 0;
119 }
120 
121 } // namespace desktop
122 } // namespace rstudio
123