← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~j-corwin/openlp/general into lp:openlp

 

Jonathan Corwin has proposed merging lp:~j-corwin/openlp/general into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #634771 in OpenLP: "OpenLP 1.9.2+bzr1016-0ubuntu1~lucid1 does not start"
  https://bugs.launchpad.net/openlp/+bug/634771
  Bug #646718 in OpenLP: "Songbook, Number will not loaded, Title will not be saved"
  https://bugs.launchpad.net/openlp/+bug/646718
  Bug #696013 in OpenLP: "song import from powerpoint crashes every second time"
  https://bugs.launchpad.net/openlp/+bug/696013
  Bug #696021 in OpenLP: "presentation loader does not work fine in Windows using Powerpoint Viewer 2007"
  https://bugs.launchpad.net/openlp/+bug/696021
  Bug #696637 in OpenLP: "Alert not positioned correctly in single screen"
  https://bugs.launchpad.net/openlp/+bug/696637
  Bug #727732 in OpenLP: "Openlp 1.9.?? crashes on start"
  https://bugs.launchpad.net/openlp/+bug/727732
  Bug #735039 in OpenLP: "Cannot import PowerPoint Presentations with PowerPoint 2010"
  https://bugs.launchpad.net/openlp/+bug/735039

For more details, see:
https://code.launchpad.net/~j-corwin/openlp/general/+merge/53718

Reverse part of the PPT 2010 fix from my previous merge which broke it for other 2010 users.
PPTviewer: Tidy code, fix problem when loading a "Loop until ESC" presentation, and overcome problems where pptviewer has decided to recently learn a new counting system.
-- 
https://code.launchpad.net/~j-corwin/openlp/general/+merge/53718
Your team OpenLP Core is requested to review the proposed merge of lp:~j-corwin/openlp/general into lp:openlp.
=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py	2011-03-15 00:10:40 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py	2011-03-16 23:40:57 +0000
@@ -80,8 +80,7 @@
             log.debug(u'start_process')
             if not self.process:
                 self.process = Dispatch(u'PowerPoint.Application')
-            if float(self.process.Version) < 13:
-                self.process.Visible = True
+            self.process.Visible = True
             self.process.WindowState = 2
 
         def kill(self):

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/ppttest.py'
--- openlp/plugins/presentations/lib/pptviewlib/ppttest.py	2011-03-15 00:10:40 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/ppttest.py	2011-03-16 23:40:57 +0000
@@ -30,19 +30,32 @@
 from ctypes.wintypes import RECT
 
 class PPTViewer(QtGui.QWidget):
+    """
+    Standalone Test Harness for the pptviewlib library
+    """
     def __init__(self, parent=None):
         QtGui.QWidget.__init__(self, parent)
         self.pptid = -1
         self.setWindowTitle(u'PowerPoint Viewer Test')
 
-        PPTLabel = QtGui.QLabel(u'Open PowerPoint file')
-        slideLabel = QtGui.QLabel(u'Go to slide #')
-        self.PPTEdit = QtGui.QLineEdit()
+        ppt_label = QtGui.QLabel(u'Open PowerPoint file')
+        slide_label = QtGui.QLabel(u'Go to slide #')
+        self.pptEdit = QtGui.QLineEdit()
         self.slideEdit = QtGui.QLineEdit()
+        x_label = QtGui.QLabel(u'X pos')
+        y_label = QtGui.QLabel(u'Y pos')
+        width_label = QtGui.QLabel(u'Width')
+        height_label = QtGui.QLabel(u'Height')
+        self.xEdit = QtGui.QLineEdit(u'100')
+        self.yEdit = QtGui.QLineEdit(u'100')
+        self.widthEdit = QtGui.QLineEdit(u'900')
+        self.heightEdit = QtGui.QLineEdit(u'700')
         self.total = QtGui.QLabel()
-        PPTBtn = QtGui.QPushButton(u'Open')
-        PPTDlgBtn = QtGui.QPushButton(u'...')
-        slideBtn = QtGui.QPushButton(u'Go')
+        ppt_btn = QtGui.QPushButton(u'Open')
+        ppt_dlg_btn = QtGui.QPushButton(u'...')
+        folder_label = QtGui.QLabel(u'Slide .bmp path')
+        self.folderEdit = QtGui.QLineEdit(u'slide')
+        slide_btn = QtGui.QPushButton(u'Go')
         prev = QtGui.QPushButton(u'Prev')
         next = QtGui.QPushButton(u'Next')
         blank = QtGui.QPushButton(u'Blank')
@@ -51,122 +64,149 @@
         close = QtGui.QPushButton(u'Close')
         resume = QtGui.QPushButton(u'Resume')
         stop = QtGui.QPushButton(u'Stop')
-        pptwindow = QtGui.QWidget()
-
         grid = QtGui.QGridLayout()
-        grid.addWidget(PPTLabel, 0, 0)
-        grid.addWidget(self.PPTEdit, 0, 1)
-        grid.addWidget(PPTDlgBtn, 0, 2)
-        grid.addWidget(PPTBtn, 0, 3)
-        grid.addWidget(slideLabel, 1, 0)
-        grid.addWidget(self.slideEdit, 1, 1)
-        grid.addWidget(slideBtn, 1, 3)
-        grid.addWidget(prev, 2, 0)
-        grid.addWidget(next, 2, 1)
-        grid.addWidget(blank, 3, 0)
-        grid.addWidget(unblank, 3, 1)
-        grid.addWidget(restart, 4, 0)
-        grid.addWidget(close, 4, 1)
-        grid.addWidget(stop, 5, 0)
-        grid.addWidget(resume, 5, 1)
-        grid.addWidget(pptwindow, 6, 0, 10, 3)
-        self.connect(PPTBtn, QtCore.SIGNAL(u'clicked()'), self.OpenClick)
-        self.connect(PPTDlgBtn, QtCore.SIGNAL(u'clicked()'), self.OpenDialog)
-        self.connect(slideBtn, QtCore.SIGNAL(u'clicked()'), self.GotoClick)
-        self.connect(prev, QtCore.SIGNAL(u'clicked()'), self.PrevClick)
-        self.connect(next, QtCore.SIGNAL(u'clicked()'), self.NextClick)
-        self.connect(blank, QtCore.SIGNAL(u'clicked()'), self.BlankClick)
-        self.connect(unblank, QtCore.SIGNAL(u'clicked()'), self.UnblankClick)
-        self.connect(restart, QtCore.SIGNAL(u'clicked()'), self.RestartClick)
-        self.connect(close, QtCore.SIGNAL(u'clicked()'), self.CloseClick)
-        self.connect(stop, QtCore.SIGNAL(u'clicked()'), self.StopClick)
-        self.connect(resume, QtCore.SIGNAL(u'clicked()'), self.ResumeClick)
-
+        row = 0
+        grid.addWidget(folder_label, 0, 0)
+        grid.addWidget(self.folderEdit, 0, 1)
+        row = row + 1
+        grid.addWidget(x_label, row, 0)
+        grid.addWidget(self.xEdit, row, 1)
+        grid.addWidget(y_label, row, 2)
+        grid.addWidget(self.yEdit, row, 3)
+        row = row + 1
+        grid.addWidget(width_label, row, 0)
+        grid.addWidget(self.widthEdit, row, 1)
+        grid.addWidget(height_label, row, 2)
+        grid.addWidget(self.heightEdit, row, 3)
+        row = row + 1        
+        grid.addWidget(ppt_label, row, 0)
+        grid.addWidget(self.pptEdit, row, 1)
+        grid.addWidget(ppt_dlg_btn, row, 2)
+        grid.addWidget(ppt_btn, row, 3)
+        row = row + 1
+        grid.addWidget(slide_label, row, 0)
+        grid.addWidget(self.slideEdit, row, 1)
+        grid.addWidget(slide_btn, row, 2)
+        row = row + 1
+        grid.addWidget(prev, row, 0)
+        grid.addWidget(next, row, 1)
+        row = row + 1
+        grid.addWidget(blank, row, 0)
+        grid.addWidget(unblank, row, 1)
+        row = row + 1
+        grid.addWidget(restart, row, 0)
+        grid.addWidget(close, row, 1)
+        row = row + 1
+        grid.addWidget(stop, row, 0)
+        grid.addWidget(resume, row, 1)
+        self.connect(ppt_btn, QtCore.SIGNAL(u'clicked()'), self.openClick)
+        self.connect(ppt_dlg_btn, QtCore.SIGNAL(u'clicked()'), self.openDialog)
+        self.connect(slide_btn, QtCore.SIGNAL(u'clicked()'), self.gotoClick)
+        self.connect(prev, QtCore.SIGNAL(u'clicked()'), self.prevClick)
+        self.connect(next, QtCore.SIGNAL(u'clicked()'), self.nextClick)
+        self.connect(blank, QtCore.SIGNAL(u'clicked()'), self.blankClick)
+        self.connect(unblank, QtCore.SIGNAL(u'clicked()'), self.unblankClick)
+        self.connect(restart, QtCore.SIGNAL(u'clicked()'), self.restartClick)
+        self.connect(close, QtCore.SIGNAL(u'clicked()'), self.closeClick)
+        self.connect(stop, QtCore.SIGNAL(u'clicked()'), self.stopClick)
+        self.connect(resume, QtCore.SIGNAL(u'clicked()'), self.resumeClick)
         self.setLayout(grid)
-
         self.resize(300, 150)
 
-    def PrevClick(self):
-        if self.pptid<0: return
-        pptdll.PrevStep(self.pptid)
-        self.UpdateCurrSlide()
-        app.processEvents()
-
-    def NextClick(self):
-        if(self.pptid<0): return
-        pptdll.NextStep(self.pptid)
-        self.UpdateCurrSlide()
-        app.processEvents()
-
-    def BlankClick(self):
-        if(self.pptid<0): return
-        pptdll.Blank(self.pptid)
-        app.processEvents()
-
-    def UnblankClick(self):
-        if(self.pptid<0): return
-        pptdll.Unblank(self.pptid)
-        app.processEvents()
-
-    def RestartClick(self):
-        if(self.pptid<0): return
-        pptdll.RestartShow(self.pptid)
-        self.UpdateCurrSlide()
-        app.processEvents()
-
-    def StopClick(self):
-        if(self.pptid<0): return
-        pptdll.Stop(self.pptid)
-        app.processEvents()
-
-    def ResumeClick(self):
-        if(self.pptid<0): return
-        pptdll.Resume(self.pptid)
-        app.processEvents()
-
-    def CloseClick(self):
-        if(self.pptid<0): return
-        pptdll.ClosePPT(self.pptid)
+    def prevClick(self):
+        if self.pptid < 0:
+            return
+        self.pptdll.PrevStep(self.pptid)
+        self.updateCurrSlide()
+        app.processEvents()
+
+    def nextClick(self):
+        if self.pptid < 0: 
+            return
+        self.pptdll.NextStep(self.pptid)
+        self.updateCurrSlide()
+        app.processEvents()
+
+    def blankClick(self):
+        if self.pptid < 0: 
+            return
+        self.pptdll.Blank(self.pptid)
+        app.processEvents()
+
+    def unblankClick(self):
+        if self.pptid < 0:
+            return
+        self.pptdll.Unblank(self.pptid)
+        app.processEvents()
+
+    def restartClick(self):
+        if self.pptid < 0: 
+            return
+        self.pptdll.RestartShow(self.pptid)
+        self.updateCurrSlide()
+        app.processEvents()
+
+    def stopClick(self):
+        if self.pptid < 0: 
+            return
+        self.pptdll.Stop(self.pptid)
+        app.processEvents()
+
+    def resumeClick(self):
+        if self.pptid < 0:
+            return
+        self.pptdll.Resume(self.pptid)
+        app.processEvents()
+
+    def closeClick(self):
+        if self.pptid < 0: 
+            return
+        self.pptdll.ClosePPT(self.pptid)
         self.pptid = -1
         app.processEvents()
 
-    def OpenClick(self):
+    def openClick(self):
         oldid = self.pptid;
-        rect = RECT(100,100,900,700)
-        filename = str(self.PPTEdit.text().replace(u'/', u'\\'))        
-        print filename
-        self.pptid = pptdll.OpenPPT(filename, None, rect, 'c:\\temp\\slide')
-        print "id: " + unicode(self.pptid)
-        if oldid>=0:
-            pptdll.ClosePPT(oldid);
-        slides = pptdll.GetSlideCount(self.pptid)
-        print "slidecount: " + unicode(slides)
-        self.total.setNum(pptdll.GetSlideCount(self.pptid))
-        self.UpdateCurrSlide()
+        rect = RECT(int(self.xEdit.text()), int(self.yEdit.text()), 
+            int(self.widthEdit.text()), int(self.heightEdit.text()))
+        filename = str(self.pptEdit.text().replace(u'/', u'\\'))   
+        folder = str(self.folderEdit.text().replace(u'/', u'\\'))   
+        print filename, folder
+        self.pptid = self.pptdll.OpenPPT(filename, None, rect, folder)
+        print u'id: ' + unicode(self.pptid)
+        if oldid >= 0:
+            self.pptdll.ClosePPT(oldid);
+        slides = self.pptdll.GetSlideCount(self.pptid)
+        print u'slidecount: ' + unicode(slides)
+        self.total.setNum(self.pptdll.GetSlideCount(self.pptid))
+        self.updateCurrSlide()
 
-    def UpdateCurrSlide(self):
-        if(self.pptid<0): return
-        slide = unicode(pptdll.GetCurrentSlide(self.pptid))
-        print "currslide: " + slide
+    def updateCurrSlide(self):
+        if self.pptid < 0: 
+            return
+        slide = unicode(self.pptdll.GetCurrentSlide(self.pptid))
+        print u'currslide: ' + slide
         self.slideEdit.setText(slide)
         app.processEvents()
 
-    def GotoClick(self):
-        if(self.pptid<0): return
+    def gotoClick(self):
+        if self.pptid < 0: 
+            return
         print self.slideEdit.text()
-        pptdll.GotoSlide(self.pptid, int(self.slideEdit.text()))
-        self.UpdateCurrSlide()
+        self.pptdll.GotoSlide(self.pptid, int(self.slideEdit.text()))
+        self.updateCurrSlide()
         app.processEvents()
 
-    def OpenDialog(self):
-        self.PPTEdit.setText(QtGui.QFileDialog.getOpenFileName(self, 'Open file'))
+    def openDialog(self):
+        self.pptEdit.setText(QtGui.QFileDialog.getOpenFileName(self, 
+            u'Open file'))
 
 if __name__ == '__main__':
-    #pptdll = cdll.LoadLibrary(r'C:\Documents and Settings\jonathan\Desktop\pptviewlib.dll')
     pptdll = cdll.LoadLibrary(r'pptviewlib.dll')
     pptdll.SetDebug(1)
-    print "Begin..."
+    print u'Begin...'
     app = QtGui.QApplication(sys.argv)
-    qb = PPTViewer()
-    qb.show()
+    window = PPTViewer()
+    window.pptdll = pptdll
+    window.show()
     sys.exit(app.exec_())

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp'
--- openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp	2011-03-15 07:34:04 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp	2011-03-16 23:40:57 +0000
@@ -1,21 +1,26 @@
-/*
- *   PPTVIEWLIB - Control PowerPoint Viewer 2003/2007 (for openlp.org)
- *   Copyright (C) 2008 Jonathan Corwin
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
+/******************************************************************************
+* PptViewLib - PowerPoint Viewer 2003/2007 Controller                         *
+* OpenLP - Open Source Lyrics Projection                                      *
+* --------------------------------------------------------------------------- *
+* Copyright (c) 2008-2011 Raoul Snyman                                        *
+* Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      *
+* Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat,  *
+* Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon  *
+* Tibble, Carsten Tinggaard, Frode Woldsund                                   *
+* --------------------------------------------------------------------------- *
+* This program is free software; you can redistribute it and/or modify it     *
+* under the terms of the GNU General Public License as published by the Free  *
+* Software Foundation; version 2 of the License.                              *
+*                                                                             *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
+* more details.                                                               *
+*                                                                             *
+* You should have received a copy of the GNU General Public License along     *
+* with this program; if not, write to the Free Software Foundation, Inc., 59  *
+* Temple Place, Suite 330, Boston, MA 02111-1307 USA                          *
+******************************************************************************/
 
 #define WIN32_LEAN_AND_MEAN  
 #include <windows.h>
@@ -27,67 +32,63 @@
 #include <sys/stat.h>
 #include "pptviewlib.h"
 
-
-// Because of the callbacks used by SetWindowsHookEx, the memory used needs to be
-// sharable across processes (the callbacks are done from a different process)
-// Therefore use data_seg with RWS memory.
+// Because of the callbacks used by SetWindowsHookEx, the memory used needs to 
+// be sharable across processes (the callbacks are done from a different 
+// process) Therefore use data_seg with RWS memory.
 //
-// See http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx for alternative
-// method of holding memory, removing fixed limits which would allow dynamic number
-// of items, rather than a fixed number. Use a Local\ mapping, since global has UAC 
-// issues in Vista.
+// See http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx for
+// alternative method of holding memory, removing fixed limits which would allow
+// dynamic number of items, rather than a fixed number. Use a Local\ mapping, 
+// since global has UAC issues in Vista.
+
 #pragma data_seg(".PPTVIEWLIB")
-PPTVIEWOBJ pptviewobj[MAX_PPTOBJS] = {NULL};
-HHOOK globalhook = NULL;
+PPTVIEW pptView[MAX_PPTS] = {NULL};
+HHOOK globalHook = NULL;
 BOOL debug = FALSE;
 #pragma data_seg()
 #pragma comment(linker, "/SECTION:.PPTVIEWLIB,RWS")
 
-#define DEBUG(...)  if(debug) printf(__VA_ARGS__)
-
-
 HINSTANCE hInstance = NULL;
 
-BOOL APIENTRY DllMain( HMODULE hModule,
-                       DWORD  ul_reason_for_call,
-                       LPVOID lpReserved
-					 )
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ulReasonForCall, 
+    LPVOID lpReserved)
 {
     hInstance = (HINSTANCE)hModule;
-	switch (ul_reason_for_call)
-	{
-	case DLL_PROCESS_ATTACH:
-		DEBUG("PROCESS_ATTACH\n");
-		break;
-	case DLL_THREAD_ATTACH:
-		DEBUG("THREAD_ATTACH\n");
-		break;
-	case DLL_THREAD_DETACH:
-		DEBUG("THREAD_DETACH\n");
-		break;
-	case DLL_PROCESS_DETACH:
-		// Clean up... hopefully there is only the one process attached? 
-		// We'll find out soon enough during tests!
-		DEBUG("PROCESS_DETACH\n");
-		for(int i = 0; i<MAX_PPTOBJS; i++)
-			ClosePPT(i);
-		break;
-	}
-	return TRUE;
+    switch(ulReasonForCall)
+    {
+        case DLL_PROCESS_ATTACH:
+            DEBUG("PROCESS_ATTACH\n");
+            break;
+        case DLL_THREAD_ATTACH:
+            //DEBUG("THREAD_ATTACH\n");
+            break;
+        case DLL_THREAD_DETACH:
+            //DEBUG("THREAD_DETACH\n");
+            break;
+        case DLL_PROCESS_DETACH:
+            // Clean up... hopefully there is only the one process attached? 
+            // We'll find out soon enough during tests!
+            DEBUG("PROCESS_DETACH\n");
+            for (int i = 0; i < MAX_PPTS; i++)
+                ClosePPT(i);
+            break;
+    }
+    return TRUE;
 }
-DllExport void SetDebug(BOOL onoff)
+
+DllExport void SetDebug(BOOL onOff)
 {
-	printf("SetDebug\n");
-	debug = onoff;
-	DEBUG("enabled\n");
+    printf("SetDebug\n");
+    debug = onOff;
+    DEBUG("enabled\n");
 }
 
 DllExport BOOL CheckInstalled()
 {
-	DEBUG("CheckInstalled\n");
-	char cmdline[MAX_PATH * 2];
+    char cmdLine[MAX_PATH * 2];
 
-	return GetPPTViewerPath(cmdline, sizeof(cmdline));
+    DEBUG("CheckInstalled\n");
+    return GetPPTViewerPath(cmdLine, sizeof(cmdLine));
 }
 
 // Open the PointPoint, count the slides and take a snapshot of each slide
@@ -96,136 +97,159 @@
 // "<n>.bmp" will be appended to complete the path. E.g. "c:\temp\slide" would 
 // create "c:\temp\slide1.bmp" slide2.bmp, slide3.bmp etc.
 // It will also create a *info.txt containing information about the ppt
-DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, char *previewpath)
+DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 
+    char *previewPath)
 {
-	STARTUPINFO si;
-	PROCESS_INFORMATION pi;
-	char cmdline[MAX_PATH * 2];
-	int id;
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    char cmdLine[MAX_PATH * 2];
+    int id;
 
-	DEBUG("OpenPPT start: %s; %s\n", filename, previewpath);
-	DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top, rect.left, rect.bottom, rect.right);
-	if(GetPPTViewerPath(cmdline, sizeof(cmdline))==FALSE)
-	{
-		DEBUG("OpenPPT: GetPPTViewerPath failed\n");
-		return -1;
-	}
-	id = -1;
-	for(int i = 0; i<MAX_PPTOBJS; i++)
-	{
-		if(pptviewobj[i].state==PPT_CLOSED)
-		{
-			id=i;
-			break;
-		}
-	}
-	if(id<0)
-	{
-		DEBUG("OpenPPT: Too many PPTs\n");
-		return -1;
-	}
-	memset(&pptviewobj[id], 0, sizeof(PPTVIEWOBJ));
-	strcpy_s(pptviewobj[id].filename, MAX_PATH, filename);
-	strcpy_s(pptviewobj[id].previewpath, MAX_PATH, previewpath);
-	pptviewobj[id].state = PPT_CLOSED;
-	pptviewobj[id].slideCount = 0;
-	pptviewobj[id].currentSlide = 0;
-	pptviewobj[id].firstSlideSteps = 0;
-	pptviewobj[id].hParentWnd = hParentWnd;
-	pptviewobj[id].hWnd = NULL;
-	pptviewobj[id].hWnd2 = NULL;
-	if(hParentWnd!=NULL&&rect.top==0&&rect.bottom==0&&rect.left==0&&rect.right==0)
-	{
-		LPRECT wndrect = NULL;
-		GetWindowRect(hParentWnd, wndrect);
-		pptviewobj[id].rect.top = 0;
-		pptviewobj[id].rect.left = 0;
-		pptviewobj[id].rect.bottom = wndrect->bottom-wndrect->top;
-		pptviewobj[id].rect.right = wndrect->right-wndrect->left;
-	}
-	else
-	{
-		pptviewobj[id].rect.top = rect.top;
-		pptviewobj[id].rect.left = rect.left;
-		pptviewobj[id].rect.bottom = rect.bottom;
-		pptviewobj[id].rect.right = rect.right;
-	}
-	strcat_s(cmdline, MAX_PATH * 2, "/F /S \"");
-	strcat_s(cmdline, MAX_PATH * 2, filename);
-	strcat_s(cmdline, MAX_PATH * 2, "\"");
-	memset(&si, 0, sizeof(si));
-	memset(&pi, 0, sizeof(pi));
-	BOOL gotinfo = GetPPTInfo(id);
-	/* 
-	 * I'd really like to just hook on the new threadid. However this always gives
-	 * error 87. Perhaps I'm hooking to soon? No idea... however can't wait
-	 * since I need to ensure I pick up the WM_CREATE as this is the only
-	 * time the window can be resized in such away the content scales correctly
-	 *
-	 * hook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,pi.dwThreadId);
-	 */
-	if(globalhook!=NULL)
-		UnhookWindowsHookEx(globalhook);
-	globalhook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,NULL);
-	if(globalhook==0)
-	{
-		DEBUG("OpenPPT: SetWindowsHookEx failed\n");
-		ClosePPT(id);
-		return -1;
-	}
-	pptviewobj[id].state = PPT_STARTED;
+    DEBUG("OpenPPT start: %s; %s\n", filename, previewPath);
+    DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top, 
+        rect.left, rect.bottom, rect.right);
+    if (GetPPTViewerPath(cmdLine, sizeof(cmdLine)) == FALSE)
+    {
+        DEBUG("OpenPPT: GetPPTViewerPath failed\n");
+        return -1;
+    }
+    id = -1;
+    for (int i = 0; i < MAX_PPTS; i++)
+    {
+        if (pptView[i].state == PPT_CLOSED)
+        {
+            id = i;
+            break;
+        }
+    }
+    if (id < 0)
+    {
+        DEBUG("OpenPPT: Too many PPTs\n");
+        return -1;
+    }
+    memset(&pptView[id], 0, sizeof(PPTVIEW));
+    strcpy_s(pptView[id].filename, MAX_PATH, filename);
+    strcpy_s(pptView[id].previewPath, MAX_PATH, previewPath);
+    pptView[id].state = PPT_CLOSED;
+    pptView[id].slideCount = 0;
+    pptView[id].currentSlide = 0;
+    pptView[id].firstSlideSteps = 0;
+    pptView[id].lastSlideSteps = 0;
+    pptView[id].guess = 0;
+    pptView[id].hParentWnd = hParentWnd;
+    pptView[id].hWnd = NULL;
+    pptView[id].hWnd2 = NULL;
+    for (int i = 0; i < MAX_SLIDES; i++)
+    {
+        pptView[id].slideNos[i] = 0;
+    }
+    if (hParentWnd != NULL && rect.top == 0 && rect.bottom == 0
+        && rect.left == 0 && rect.right == 0)
+    {
+        LPRECT windowRect = NULL;
+        GetWindowRect(hParentWnd, windowRect);
+        pptView[id].rect.top = 0;
+        pptView[id].rect.left = 0;
+        pptView[id].rect.bottom = windowRect->bottom - windowRect->top;
+        pptView[id].rect.right = windowRect->right - windowRect->left;
+    }
+    else
+    {
+        pptView[id].rect.top = rect.top;
+        pptView[id].rect.left = rect.left;
+        pptView[id].rect.bottom = rect.bottom;
+        pptView[id].rect.right = rect.right;
+    }
+    strcat_s(cmdLine, MAX_PATH * 2, "/F /S \"");
+    strcat_s(cmdLine, MAX_PATH * 2, filename);
+    strcat_s(cmdLine, MAX_PATH * 2, "\"");
+    memset(&si, 0, sizeof(si));
+    memset(&pi, 0, sizeof(pi));
+    BOOL gotInfo = GetPPTInfo(id);
+    /* 
+     * I'd really like to just hook on the new threadid. However this always 
+     * gives error 87. Perhaps I'm hooking to soon? No idea... however can't 
+     * wait since I need to ensure I pick up the WM_CREATE as this is the only
+     * time the window can be resized in such away the content scales correctly
+     *
+     * hook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,pi.dwThreadId);
+     */
+    if (globalHook != NULL)
+    {
+        UnhookWindowsHookEx(globalHook);
+    }
+    globalHook = SetWindowsHookEx(WH_CBT, CbtProc, hInstance, NULL);
+    if (globalHook == 0)
+    {
+        DEBUG("OpenPPT: SetWindowsHookEx failed\n");
+        ClosePPT(id);
+        return -1;
+    }
+    pptView[id].state = PPT_STARTED;
     Sleep(10); 
-	if(!CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi))
-	{
-		DEBUG("OpenPPT: CreateProcess failed\n");
-		ClosePPT(id);
-		return -1;
-	}
-	pptviewobj[id].dwProcessId = pi.dwProcessId;
-	pptviewobj[id].dwThreadId = pi.dwThreadId;
-	pptviewobj[id].hThread = pi.hThread;
-	pptviewobj[id].hProcess = pi.hProcess;
-	while(pptviewobj[id].state==PPT_STARTED)
-		Sleep(10);
-	if(gotinfo)
-	{
-		DEBUG("OpenPPT: Info loaded, no refresh\n");
-		pptviewobj[id].state = PPT_LOADED;
-		Resume(id);
-	}
-	else
-	{
-		DEBUG("OpenPPT: Get info\n");
-		pptviewobj[id].steps = 0;
-		int steps = 0;
-		while(pptviewobj[id].state==PPT_OPENED)
-		{
-			if(steps<=pptviewobj[id].steps)
-			{
-				Sleep(20);
-				DEBUG("OpenPPT: Step %d/%d\n",steps,pptviewobj[id].steps);
-				steps++;
-				NextStep(id);
-			} 
-			Sleep(10);
-		}
-		DEBUG("OpenPPT: Steps %d, first slide steps %d\n",pptviewobj[id].steps,pptviewobj[id].firstSlideSteps);
-		SavePPTInfo(id);
-	    if(pptviewobj[id].state==PPT_CLOSING||pptviewobj[id].slideCount<=0){
-	        ClosePPT(id);
-	        id=-1;
-	    }
-		else
-       		RestartShow(id);
-	}
-	if(id>=0)
-	{
-	    if(pptviewobj[id].mhook!=NULL)	
-		    UnhookWindowsHookEx(pptviewobj[id].mhook);
-	    pptviewobj[id].mhook = NULL;
-	}
-	DEBUG("OpenPPT: Exit: id=%i\n", id);
-	return id;
+    if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi))
+    {
+        DEBUG("OpenPPT: CreateProcess failed\n");
+        ClosePPT(id);
+        return -1;
+    }
+    pptView[id].dwProcessId = pi.dwProcessId;
+    pptView[id].dwThreadId = pi.dwThreadId;
+    pptView[id].hThread = pi.hThread;
+    pptView[id].hProcess = pi.hProcess;
+    while (pptView[id].state == PPT_STARTED)
+        Sleep(10);
+    if (gotInfo)
+    {
+        DEBUG("OpenPPT: Info loaded, no refresh\n");
+        pptView[id].state = PPT_LOADED;
+        Resume(id);
+    }
+    else
+    {
+        DEBUG("OpenPPT: Get info\n");
+        pptView[id].steps = 0;
+        int steps = 0;
+        while (pptView[id].state == PPT_OPENED)
+        {
+            if (steps <= pptView[id].steps)
+            {
+                Sleep(20);
+                DEBUG("OpenPPT: Step %d/%d\n", steps, pptView[id].steps);
+                steps++;
+                NextStep(id);
+            } 
+            Sleep(10);
+        }
+        DEBUG("OpenPPT: Slides %d, Steps %d, first slide steps %d\n",
+            pptView[id].slideCount, pptView[id].steps, 
+            pptView[id].firstSlideSteps);
+        for(int i = 1; i <= pptView[id].slideCount; i++)
+        {
+            DEBUG("OpenPPT: Slide %d = %d\n", i, pptView[id].slideNos[i]);
+        }
+        SavePPTInfo(id);
+        if (pptView[id].state == PPT_CLOSING 
+            || pptView[id].slideCount <= 0)
+        {
+            ClosePPT(id);
+            id=-1;
+        }
+        else 
+        {
+               RestartShow(id);
+        }
+    }
+    if (id >= 0)
+    {
+        if (pptView[id].msgHook != NULL)
+        {
+            UnhookWindowsHookEx(pptView[id].msgHook);
+        }
+        pptView[id].msgHook = NULL;
+    }
+    DEBUG("OpenPPT: Exit: id=%i\n", id);
+    return id;
 }
 // Load information about the ppt from an info.txt file.
 // Format:
@@ -236,292 +260,316 @@
 // first slide steps
 BOOL GetPPTInfo(int id)
 {
-	struct _stat filestats;
-	char info[MAX_PATH];
-	FILE* pFile;
-	char buf[100];
+    struct _stat fileStats;
+    char info[MAX_PATH];
+    FILE* pFile;
+    char buf[100];
 
-	DEBUG("GetPPTInfo: start\n");
-	if(_stat(pptviewobj[id].filename, &filestats)!=0)
-		return FALSE;
-	sprintf_s(info, MAX_PATH, "%sinfo.txt", pptviewobj[id].previewpath);
-	int err = fopen_s(&pFile, info, "r");
-	if(err!=0)
-	{
-		DEBUG("GetPPTInfo: file open failed - %d\n", err);
-		return FALSE;
-	}
-	fgets(buf, 100, pFile); // version == 1
-	fgets(buf, 100, pFile); 
-	if(filestats.st_mtime!=atoi(buf))
-	{
-		fclose (pFile);
-		return FALSE;
-	}
-	fgets(buf, 100, pFile);	
-	if(filestats.st_size!=atoi(buf))
-	{
-		fclose (pFile);
-		return FALSE;
-	}
-	fgets(buf, 100, pFile); // slidecount
-	int slidecount = atoi(buf);
-	fgets(buf, 100, pFile); // first slide steps
-	int firstslidesteps = atoi(buf);
-	// check all the preview images still exist
-	for(int i = 1; i<=slidecount; i++)
-	{
-		sprintf_s(info, MAX_PATH, "%s%i.bmp", pptviewobj[id].previewpath, i);
-		if(GetFileAttributes(info)==INVALID_FILE_ATTRIBUTES)
-			return FALSE;
-	}
-	fclose(pFile);
-	pptviewobj[id].slideCount = slidecount;
-	pptviewobj[id].firstSlideSteps = firstslidesteps;
-	DEBUG("GetPPTInfo: exit ok\n");
-	return TRUE;
+    DEBUG("GetPPTInfo: start\n");
+    if (_stat(pptView[id].filename, &fileStats) != 0)
+    {
+        return FALSE;
+    }
+    sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath);
+    int err = fopen_s(&pFile, info, "r");
+    if (err != 0)
+    {
+        DEBUG("GetPPTInfo: file open failed - %d\n", err);
+        return FALSE;
+    }
+    fgets(buf, 100, pFile); // version == 1
+    fgets(buf, 100, pFile); 
+    if (fileStats.st_mtime != atoi(buf))
+    {
+        DEBUG("GetPPTInfo: date changed\n");
+        fclose (pFile);
+        return FALSE;
+    }
+    fgets(buf, 100, pFile);    
+    if (fileStats.st_size != atoi(buf))
+    {
+        DEBUG("GetPPTInfo: size changed\n");
+        fclose (pFile);
+        return FALSE;
+    }
+    fgets(buf, 100, pFile); // slidecount
+    int slideCount = atoi(buf);
+    fgets(buf, 100, pFile); // first slide steps
+    int firstSlideSteps = atoi(buf);
+    // check all the preview images still exist
+    for (int i = 1; i <= slideCount; i++)
+    {
+        sprintf_s(info, MAX_PATH, "%s%i.bmp", pptView[id].previewPath, i);
+        if (GetFileAttributes(info) == INVALID_FILE_ATTRIBUTES)
+        {
+            DEBUG("GetPPTInfo: bmp not found\n");
+            return FALSE;
+        }
+    }
+    fclose(pFile);
+    pptView[id].slideCount = slideCount;
+    pptView[id].firstSlideSteps = firstSlideSteps;
+    DEBUG("GetPPTInfo: exit ok\n");
+    return TRUE;
 }
 
 BOOL SavePPTInfo(int id)
 {
-	struct _stat filestats;
-	char info[MAX_PATH];
-	FILE* pFile;
+    struct _stat fileStats;
+    char info[MAX_PATH];
+    FILE* pFile;
 
-	DEBUG("SavePPTInfo: start\n");
-	if(_stat(pptviewobj[id].filename, &filestats)!=0)
-	{
-		DEBUG("SavePPTInfo: stat of %s failed\n", pptviewobj[id].filename);
-		return FALSE;
-	}
-	sprintf_s(info, MAX_PATH, "%sinfo.txt", pptviewobj[id].previewpath);
-	int err = fopen_s(&pFile, info, "w");
-	if(err!=0)
-	{
-		DEBUG("SavePPTInfo: fopen of %s failed%i\n", info, err);
-		return FALSE;
-	}
-	fprintf(pFile, "1\n");
-	fprintf(pFile, "%u\n", filestats.st_mtime);
-	fprintf(pFile, "%u\n", filestats.st_size);
-	fprintf(pFile, "%u\n", pptviewobj[id].slideCount);
-	fprintf(pFile, "%u\n", pptviewobj[id].firstSlideSteps);
-	fclose (pFile);
-	DEBUG("SavePPTInfo: exit ok\n");
-	return TRUE;
+    DEBUG("SavePPTInfo: start\n");
+    if (_stat(pptView[id].filename, &fileStats) != 0)
+    {
+        DEBUG("SavePPTInfo: stat of %s failed\n", pptView[id].filename);
+        return FALSE;
+    }
+    sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath);
+    int err = fopen_s(&pFile, info, "w");
+    if (err != 0)
+    {
+        DEBUG("SavePPTInfo: fopen of %s failed%i\n", info, err);
+        return FALSE;
+    }
+    fprintf(pFile, "1\n");
+    fprintf(pFile, "%u\n", fileStats.st_mtime);
+    fprintf(pFile, "%u\n", fileStats.st_size);
+    fprintf(pFile, "%u\n", pptView[id].slideCount);
+    fprintf(pFile, "%u\n", pptView[id].firstSlideSteps);
+    fclose(pFile);
+    DEBUG("SavePPTInfo: exit ok\n");
+    return TRUE;
 }
 
 // Get the path of the PowerPoint viewer from the registry
-BOOL GetPPTViewerPath(char *pptviewerpath, int strsize)
+BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize)
 {
-	HKEY hkey;
-	DWORD dwtype, dwsize;
-	LRESULT lresult;
+    HKEY hKey;
+    DWORD dwType, dwSize;
+    LRESULT lResult;
 
-	DEBUG("GetPPTViewerPath: start\n");
-	if(RegOpenKeyEx(HKEY_CLASSES_ROOT, "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hkey)!=ERROR_SUCCESS)
-		if(RegOpenKeyEx(HKEY_CLASSES_ROOT, "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hkey)!=ERROR_SUCCESS)
-    		if(RegOpenKeyEx(HKEY_CLASSES_ROOT, "Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hkey)!=ERROR_SUCCESS)
-				return FALSE;	
-	dwtype = REG_SZ;
-	dwsize = (DWORD)strsize;
-	lresult = RegQueryValueEx(hkey, NULL, NULL, &dwtype, (LPBYTE)pptviewerpath, &dwsize );
-	RegCloseKey(hkey);
-	if(lresult!=ERROR_SUCCESS)
-		return FALSE;
-	pptviewerpath[strlen(pptviewerpath)-4] = '\0';	// remove "%1" from end of key value
-	DEBUG("GetPPTViewerPath: exit ok\n");
-	return TRUE;
+    DEBUG("GetPPTViewerPath: start\n");
+    if ((RegOpenKeyEx(HKEY_CLASSES_ROOT, 
+        "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey)
+        != ERROR_SUCCESS)
+        && (RegOpenKeyEx(HKEY_CLASSES_ROOT, 
+        "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey)
+        != ERROR_SUCCESS)
+        && (RegOpenKeyEx(HKEY_CLASSES_ROOT, 
+        "Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hKey)
+        != ERROR_SUCCESS))
+    {
+        return FALSE;
+    }
+    dwType = REG_SZ;
+    dwSize = (DWORD)stringSize;
+    lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)pptViewerPath, 
+        &dwSize);
+    RegCloseKey(hKey);
+    if (lResult != ERROR_SUCCESS)
+    {
+        return FALSE;
+    }
+    // remove "%1" from end of key value
+    pptViewerPath[strlen(pptViewerPath) - 4] = '\0';    
+    DEBUG("GetPPTViewerPath: exit ok\n");
+    return TRUE;
 }
 
 // Unhook the Windows hook 
 void Unhook(int id)
 {
-	DEBUG("Unhook: start %d\n", id);
-	if(pptviewobj[id].hook!=NULL)	
-		UnhookWindowsHookEx(pptviewobj[id].hook);
-	if(pptviewobj[id].mhook!=NULL)	
-		UnhookWindowsHookEx(pptviewobj[id].mhook);
-	pptviewobj[id].hook = NULL;
-	pptviewobj[id].mhook = NULL;
-	DEBUG("Unhook: exit ok\n");
+    DEBUG("Unhook: start %d\n", id);
+    if (pptView[id].hook != NULL)    
+    {
+        UnhookWindowsHookEx(pptView[id].hook);
+    }
+    if (pptView[id].msgHook != NULL)
+    {
+        UnhookWindowsHookEx(pptView[id].msgHook);
+    }
+    pptView[id].hook = NULL;
+    pptView[id].msgHook = NULL;
+    DEBUG("Unhook: exit ok\n");
 }
 
 // Close the PowerPoint viewer, release resources
 DllExport void ClosePPT(int id)
 {
-	DEBUG("ClosePPT: start%d\n", id);
-	pptviewobj[id].state = PPT_CLOSED;
-	Unhook(id);
-	if(pptviewobj[id].hWnd==0)
-		TerminateThread(pptviewobj[id].hThread, 0);
-	else
-		PostMessage(pptviewobj[id].hWnd, WM_CLOSE, 0, 0);
-	CloseHandle(pptviewobj[id].hThread);
-	CloseHandle(pptviewobj[id].hProcess);
-	memset(&pptviewobj[id], 0, sizeof(PPTVIEWOBJ));
-	DEBUG("ClosePPT: exit ok\n");
-	return;
+    DEBUG("ClosePPT: start%d\n", id);
+    pptView[id].state = PPT_CLOSED;
+    Unhook(id);
+    if (pptView[id].hWnd == 0)
+    {
+        TerminateThread(pptView[id].hThread, 0);
+    }
+    else
+    {
+        PostMessage(pptView[id].hWnd, WM_CLOSE, 0, 0);
+    }
+    CloseHandle(pptView[id].hThread);
+    CloseHandle(pptView[id].hProcess);
+    memset(&pptView[id], 0, sizeof(PPTVIEW));
+    DEBUG("ClosePPT: exit ok\n");
+    return;
 }
 // Moves the show back onto the display
 DllExport void Resume(int id)
 {
-	DEBUG("Resume: %d\n", id);
-	MoveWindow(pptviewobj[id].hWnd, pptviewobj[id].rect.left, pptviewobj[id].rect.top, 
-			pptviewobj[id].rect.right - pptviewobj[id].rect.left, 
-			pptviewobj[id].rect.bottom - pptviewobj[id].rect.top, TRUE);
-	Unblank(id);								
+    DEBUG("Resume: %d\n", id);
+    MoveWindow(pptView[id].hWnd, pptView[id].rect.left, 
+        pptView[id].rect.top, 
+        pptView[id].rect.right - pptView[id].rect.left, 
+        pptView[id].rect.bottom - pptView[id].rect.top, TRUE);
+    Unblank(id);                                
 }
 // Moves the show off the screen so it can't be seen
 DllExport void Stop(int id)
 {
-	DEBUG("Stop:%d\n", id);
-	MoveWindow(pptviewobj[id].hWnd, -32000, -32000, 
-			pptviewobj[id].rect.right - pptviewobj[id].rect.left, 
-			pptviewobj[id].rect.bottom - pptviewobj[id].rect.top, TRUE);
+    DEBUG("Stop:%d\n", id);
+    MoveWindow(pptView[id].hWnd, -32000, -32000, 
+        pptView[id].rect.right - pptView[id].rect.left, 
+        pptView[id].rect.bottom - pptView[id].rect.top, TRUE);
 }
 
 // Return the total number of slides
 DllExport int GetSlideCount(int id)
 {
-	DEBUG("GetSlideCount:%d\n", id);
-	if(pptviewobj[id].state==0)
-		return -1;
-	else
-		return pptviewobj[id].slideCount;
+    DEBUG("GetSlideCount:%d\n", id);
+    if (pptView[id].state == 0)
+    {
+        return -1;
+    }
+    else
+    {
+        return pptView[id].slideCount;
+    }
 }
 
 // Return the number of the slide currently viewing
 DllExport int GetCurrentSlide(int id)
 {
-	DEBUG("GetCurrentSlide:%d\n", id);
-	if(pptviewobj[id].state==0)
-		return -1;
-	else
-		return pptviewobj[id].currentSlide;
+    DEBUG("GetCurrentSlide:%d\n", id);
+    if (pptView[id].state == 0)
+    {
+        return -1;
+    }
+    else
+    {
+        return pptView[id].currentSlide;
+    }
 }
 
 // Take a step forwards through the show 
 DllExport void NextStep(int id)
 {
-	DEBUG("NextStep:%d\n", id);
-	if(pptviewobj[id].currentSlide>pptviewobj[id].slideCount)
-		return;
-	PostMessage(pptviewobj[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), 0);
+    DEBUG("NextStep:%d (%d)\n", id, pptView[id].currentSlide);
+    if (pptView[id].currentSlide > pptView[id].slideCount) return;
+    if (pptView[id].currentSlide < pptView[id].slideCount)
+    {
+        pptView[id].guess = pptView[id].currentSlide + 1;
+    }
+    PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), 
+        0);
 }
 
 // Take a step backwards through the show 
 DllExport void PrevStep(int id)
 {
-	DEBUG("PrevStep:%d\n", id);
-	PostMessage(pptviewobj[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0);
+    DEBUG("PrevStep:%d (%d)\n", id, pptView[id].currentSlide);
+    if (pptView[id].currentSlide > 1)
+    {
+        pptView[id].guess = pptView[id].currentSlide - 1;
+    }
+    PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 
+        0);
 }
 
 // Blank the show (black screen)
 DllExport void Blank(int id)
-{	
-	// B just toggles blank on/off. However pressing any key unblanks.
-	// So send random unmapped letter first (say 'A'), then we can 
-	// better guarantee B will blank instead of trying to guess 
-	// whether it was already blank or not.
-	DEBUG("Blank:%d\n", id);
-	HWND h1 = GetForegroundWindow();
-	HWND h2 = GetFocus();
-	SetForegroundWindow(pptviewobj[id].hWnd);
-	SetFocus(pptviewobj[id].hWnd);
-	Sleep(50);	// slight pause, otherwise event triggering this call may grab focus back!
-	keybd_event((int)'A', 0, 0, 0);
-	keybd_event((int)'A', 0, KEYEVENTF_KEYUP, 0);
-	keybd_event((int)'B', 0, 0, 0);
-	keybd_event((int)'B', 0, KEYEVENTF_KEYUP, 0);
-	SetForegroundWindow(h1);
-	SetFocus(h2);
-	//PostMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, 'B', 0x00300001);
-	//PostMessage(pptviewobj[id].hWnd2, WM_CHAR, 'b', 0x00300001);
-	//PostMessage(pptviewobj[id].hWnd2, WM_KEYUP, 'B', 0xC0300001);
+{    
+    // B just toggles blank on/off. However pressing any key unblanks.
+    // So send random unmapped letter first (say 'A'), then we can 
+    // better guarantee B will blank instead of trying to guess 
+    // whether it was already blank or not.
+    DEBUG("Blank:%d\n", id);
+    HWND h1 = GetForegroundWindow();
+    HWND h2 = GetFocus();
+    SetForegroundWindow(pptView[id].hWnd);
+    SetFocus(pptView[id].hWnd);
+    // slight pause, otherwise event triggering this call may grab focus back!
+    Sleep(50);    
+    keybd_event((int)'A', 0, 0, 0);
+    keybd_event((int)'A', 0, KEYEVENTF_KEYUP, 0);
+    keybd_event((int)'B', 0, 0, 0);
+    keybd_event((int)'B', 0, KEYEVENTF_KEYUP, 0);
+    SetForegroundWindow(h1);
+    SetFocus(h2);
 }
 // Unblank the show 
 DllExport void Unblank(int id)
-{	
-	DEBUG("Unblank:%d\n", id);
-	// Pressing any key resumes. 
-	// For some reason SendMessage works for unblanking, but not blanking.
-//	SendMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, 'A', 0);
-	SendMessage(pptviewobj[id].hWnd2, WM_CHAR, 'A', 0);
-//	SendMessage(pptviewobj[id].hWnd2, WM_KEYUP, 'A', 0);
-//	HWND h1 = GetForegroundWindow();
-//	HWND h2 = GetFocus();
-//	Sleep(50);	// slight pause, otherwise event triggering this call may grab focus back!
-//	SetForegroundWindow(pptviewobj[id].hWnd);
-//	SetFocus(pptviewobj[id].hWnd);
-//	keybd_event((int)'A', 0, 0, 0);
-//	SetForegroundWindow(h1);
-//	SetFocus(h2);
+{    
+    DEBUG("Unblank:%d\n", id);
+    // Pressing any key resumes. 
+    // For some reason SendMessage works for unblanking, but not blanking.
+    SendMessage(pptView[id].hWnd2, WM_CHAR, 'A', 0);
 }
 
 // Go directly to a slide
-DllExport void GotoSlide(int id, int slideno)
-{	
-	DEBUG("GotoSlide %i %i:\n", id, slideno);
-	// Did try WM_KEYDOWN/WM_CHAR/WM_KEYUP with SendMessage but didn't work
-	// perhaps I was sending to the wrong window? No idea. 
-	// Anyway fall back to keybd_event, which is OK as long we makesure
-	// the slideshow has focus first
-	char ch[10];
-
-	if(slideno<0) return;
-	_itoa_s(slideno, ch, 10, 10);
-	HWND h1 = GetForegroundWindow();
-	HWND h2 = GetFocus();
-	SetForegroundWindow(pptviewobj[id].hWnd);
-	SetFocus(pptviewobj[id].hWnd);
-	Sleep(50);	// slight pause, otherwise event triggering this call may grab focus back!
-	for(int i=0;i<10;i++)
-	{
-		if(ch[i]=='\0') break;
-		keybd_event((BYTE)ch[i], 0, 0, 0);
-		keybd_event((BYTE)ch[i], 0, KEYEVENTF_KEYUP, 0);
-	}
-	keybd_event(VK_RETURN, 0, 0, 0);
-	keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
-	SetForegroundWindow(h1);
-	SetFocus(h2);
-
-	//for(int i=0;i<10;i++)
-	//{
-	//	if(ch[i]=='\0') break;
-	//	SendMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, ch[i], 0);
-	//	SendMessage(pptviewobj[id].hWnd2, WM_CHAR, ch[i], 0);
-	//	SendMessage(pptviewobj[id].hWnd2, WM_KEYUP, ch[i], 0);
-	//}
-	//SendMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, VK_RETURN, 0);
-	//SendMessage(pptviewobj[id].hWnd2, WM_CHAR, VK_RETURN, 0);
-	//SendMessage(pptviewobj[id].hWnd2, WM_KEYUP, VK_RETURN, 0);
-	//keybd_event(VK_RETURN, 0, 0, 0);
+DllExport void GotoSlide(int id, int slideNo)
+{    
+    DEBUG("GotoSlide %i %i:\n", id, slideNo);
+    // Did try WM_KEYDOWN/WM_CHAR/WM_KEYUP with SendMessage but didn't work
+    // perhaps I was sending to the wrong window? No idea. 
+    // Anyway fall back to keybd_event, which is OK as long we makesure
+    // the slideshow has focus first
+    char ch[10];
+
+    if (slideNo < 0) return;
+    pptView[id].guess = slideNo;
+    _itoa_s(slideNo, ch, 10, 10);
+    HWND h1 = GetForegroundWindow();
+    HWND h2 = GetFocus();
+    SetForegroundWindow(pptView[id].hWnd);
+    SetFocus(pptView[id].hWnd);
+    // slight pause, otherwise event triggering this call may grab focus back!
+    Sleep(50);    
+    for (int i=0; i<10; i++)
+    {
+        if (ch[i] == '\0') break;
+        keybd_event((BYTE)ch[i], 0, 0, 0);
+        keybd_event((BYTE)ch[i], 0, KEYEVENTF_KEYUP, 0);
+    }
+    keybd_event(VK_RETURN, 0, 0, 0);
+    keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
+    SetForegroundWindow(h1);
+    SetFocus(h2);
 }
 
 // Restart the show from the beginning
 DllExport void RestartShow(int id)
 {
-	// If we just go direct to slide one, then it remembers that all other slides have
-	// been animated, so ends up just showing the completed slides of those slides that
-	// have been animated next time we advance. 
-	// Only way I've found to get around this is to step backwards all the way through. 
-	// Lets move the window out of the way first so the audience doesn't see this.
-	DEBUG("RestartShow:%d\n", id);
-	Stop(id);
-	GotoSlide(id, pptviewobj[id].slideCount);
-	while(pptviewobj[id].currentSlide>1)
-	{
-		PrevStep(id);
-		Sleep(10);
-	}
-	for(int i=0;i<=pptviewobj[id].firstSlideSteps;i++)
-	{
-		PrevStep(id);
-		Sleep(10);
-	}
-	Resume(id);
+    // If we just go direct to slide one, then it remembers that all other 
+    // slides have been animated, so ends up just showing the completed slides 
+    // of those slides that have been animated next time we advance. 
+    // Only way I've found to get around this is to step backwards all the way 
+    // through. Lets move the window out of the way first so the audience 
+    // doesn't see this.
+    DEBUG("RestartShow:%d\n", id);
+    Stop(id);
+    GotoSlide(id, pptView[id].slideCount);
+    for (int i=0; i <= pptView[id].steps - pptView[id].lastSlideSteps; i++)
+    {
+        PrevStep(id);
+        Sleep(10);
+    }
+    int i = 0;
+    while ((pptView[id].currentSlide > 1) && (i++ < 30000))
+    {
+        Sleep(10);
+    }
+    Resume(id);
 }
 
 // This hook is started with the PPTVIEW.EXE process and waits for the
@@ -530,234 +578,287 @@
 // Release the hook as soon as we're complete to free up resources
 LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam)
 {
-	HHOOK hook = globalhook;
-    if(nCode==HCBT_CREATEWND)
+    HHOOK hook = globalHook;
+    if (nCode == HCBT_CREATEWND)
     {
-	    char csClassName[16];
+        char csClassName[16];
         HWND hCurrWnd = (HWND)wParam;
-		DWORD retProcId = NULL;
-		GetClassName(hCurrWnd, csClassName, sizeof(csClassName));
-		if((strcmp(csClassName, "paneClassDC")==0)
-		  ||(strcmp(csClassName, "screenClass")==0))
-		{
-			int id=-1;
-			DWORD windowthread = GetWindowThreadProcessId(hCurrWnd,NULL);
-			for(int i=0; i<MAX_PPTOBJS; i++)
-			{
-				if(pptviewobj[i].dwThreadId==windowthread)
-				{
-					id=i;
-					break;
-				}
-			}
-			if(id>=0)
-			{
-				if(strcmp(csClassName, "paneClassDC")==0)
-					pptviewobj[id].hWnd2=hCurrWnd;
-				else		
-				{
-					pptviewobj[id].hWnd=hCurrWnd;
-					CBT_CREATEWND* cw = (CBT_CREATEWND*)lParam;
-					if(pptviewobj[id].hParentWnd!=NULL) 
-						cw->lpcs->hwndParent = pptviewobj[id].hParentWnd;
-					cw->lpcs->cy=(pptviewobj[id].rect.bottom-pptviewobj[id].rect.top);
-					cw->lpcs->cx=(pptviewobj[id].rect.right-pptviewobj[id].rect.left);
-					cw->lpcs->y=-32000; 
-					cw->lpcs->x=-32000; 
-				}
-				if((pptviewobj[id].hWnd!=NULL)&&(pptviewobj[id].hWnd2!=NULL))
-				{
-					UnhookWindowsHookEx(globalhook);
-					globalhook=NULL;
-					pptviewobj[id].hook = SetWindowsHookEx(WH_CALLWNDPROC,CwpProc,hInstance,pptviewobj[id].dwThreadId);
-					pptviewobj[id].mhook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInstance,pptviewobj[id].dwThreadId);
-					Sleep(10);
-					pptviewobj[id].state = PPT_OPENED;
-				}
-			}
-		}
+        DWORD retProcId = NULL;
+        GetClassName(hCurrWnd, csClassName, sizeof(csClassName));
+        if ((strcmp(csClassName, "paneClassDC") == 0)
+          ||(strcmp(csClassName, "screenClass") == 0))
+        {
+            int id = -1;
+            DWORD windowThread = GetWindowThreadProcessId(hCurrWnd, NULL);
+            for (int i=0; i < MAX_PPTS; i++)
+            {
+                if (pptView[i].dwThreadId == windowThread)
+                {
+                    id = i;
+                    break;
+                }
+            }
+            if (id >= 0)
+            {
+                if (strcmp(csClassName, "paneClassDC") == 0)
+                {
+                    pptView[id].hWnd2 = hCurrWnd;
+                }
+                else        
+                {
+                    pptView[id].hWnd = hCurrWnd;
+                    CBT_CREATEWND* cw = (CBT_CREATEWND*)lParam;
+                    if (pptView[id].hParentWnd != NULL) 
+                    {
+                        cw->lpcs->hwndParent = pptView[id].hParentWnd;
+                    }
+                    cw->lpcs->cy = pptView[id].rect.bottom 
+                        - pptView[id].rect.top;
+                    cw->lpcs->cx = pptView[id].rect.right
+                        - pptView[id].rect.left;
+                    cw->lpcs->y = -32000; 
+                    cw->lpcs->x = -32000; 
+                }
+                if ((pptView[id].hWnd != NULL) && (pptView[id].hWnd2 != NULL))
+                {
+                    UnhookWindowsHookEx(globalHook);
+                    globalHook = NULL;
+                    pptView[id].hook = SetWindowsHookEx(WH_CALLWNDPROC,
+                        CwpProc, hInstance, pptView[id].dwThreadId);
+                    pptView[id].msgHook = SetWindowsHookEx(WH_GETMESSAGE,
+                        GetMsgProc, hInstance, pptView[id].dwThreadId);
+                    Sleep(10);
+                    pptView[id].state = PPT_OPENED;
+                }
+            }
+        }
     }
-	return CallNextHookEx(hook,nCode,wParam,lParam); 
+    return CallNextHookEx(hook, nCode, wParam, lParam); 
 }
 
 // This hook exists whilst the slideshow is loading but only listens on the
 // slideshows thread. It listens out for mousewheel events
 LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) 
 {
-	HHOOK hook = NULL;
-	MSG *pMSG = (MSG *)lParam;
-	DWORD windowthread = GetWindowThreadProcessId(pMSG->hwnd,NULL);
-	int id=-1;
-	for(int i=0; i<MAX_PPTOBJS; i++)
-	{
-		if(pptviewobj[i].dwThreadId==windowthread)
-		{
-			id=i;
-			hook = pptviewobj[id].mhook;
-			break;
-		}
-	}
-	if(id>=0&&nCode==HC_ACTION&&wParam==PM_REMOVE&&pMSG->message==WM_MOUSEWHEEL)
-    {
-		if(pptviewobj[id].state!=PPT_LOADED)
-		{
-			if(pptviewobj[id].currentSlide==1)
-				pptviewobj[id].firstSlideSteps++;
-			pptviewobj[id].steps++;
-		}
+    HHOOK hook = NULL;
+    MSG *pMSG = (MSG *)lParam;
+    DWORD windowThread = GetWindowThreadProcessId(pMSG->hwnd, NULL);
+    int id = -1;
+    for (int i = 0; i < MAX_PPTS; i++)
+    {
+        if (pptView[i].dwThreadId == windowThread)
+        {
+            id = i;
+            hook = pptView[id].msgHook;
+            break;
+        }
+    }
+    if (id >= 0 && nCode == HC_ACTION && wParam == PM_REMOVE 
+        && pMSG->message == WM_MOUSEWHEEL)
+    {
+        if (pptView[id].state != PPT_LOADED)
+        {
+            if (pptView[id].currentSlide == 1)
+            {
+                pptView[id].firstSlideSteps++;
+            }
+            pptView[id].steps++;
+            pptView[id].lastSlideSteps++;
+        }
     }
     return CallNextHookEx(hook, nCode, wParam, lParam);
 }
 // This hook exists whilst the slideshow is running but only listens on the
 // slideshows thread. It listens out for slide changes, message WM_USER+22.
 LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){
-	CWPSTRUCT *cwp;
-	cwp = (CWPSTRUCT *)lParam;
-	HHOOK hook = NULL;
-	char filename[MAX_PATH];
-
-	DWORD windowthread = GetWindowThreadProcessId(cwp->hwnd,NULL);
-	int id=-1;
-	for(int i=0; i<MAX_PPTOBJS; i++)
-	{
-		if(pptviewobj[i].dwThreadId==windowthread)
-		{
-			id=i;
-			hook = pptviewobj[id].hook;
-			break;
-		}
-	}
-	if((id>=0)&&(nCode==HC_ACTION))
-	{
-		if(cwp->message==WM_USER+22)
-		{
-			if(pptviewobj[id].state != PPT_LOADED)
-			{
-				if((pptviewobj[id].currentSlide>0)
-				&& (pptviewobj[id].previewpath!=NULL&&strlen(pptviewobj[id].previewpath)>0))
-				{
-					sprintf_s(filename, MAX_PATH, "%s%i.bmp", pptviewobj[id].previewpath, pptviewobj[id].currentSlide);
-					CaptureAndSaveWindow(cwp->hwnd, filename);
-				}
-			}
-			if(cwp->wParam==0)
-			{
-				if(pptviewobj[id].currentSlide>0) 
-				{
-					pptviewobj[id].state = PPT_LOADED;
-					pptviewobj[id].currentSlide = pptviewobj[id].slideCount+1;
-				}
-			} 
-			else
-			{
-				pptviewobj[id].currentSlide = cwp->wParam - 255;
-				if(pptviewobj[id].currentSlide>pptviewobj[id].slideCount)
-					pptviewobj[id].slideCount = pptviewobj[id].currentSlide;
-			}
-		}
-		if((pptviewobj[id].state != PPT_CLOSED)&&(cwp->message==WM_CLOSE||cwp->message==WM_QUIT))
-			pptviewobj[id].state = PPT_CLOSING;
-	}
-	return CallNextHookEx(hook,nCode,wParam,lParam); 
+    CWPSTRUCT *cwp;
+    cwp = (CWPSTRUCT *)lParam;
+    HHOOK hook = NULL;
+    char filename[MAX_PATH];
+
+    DWORD windowThread = GetWindowThreadProcessId(cwp->hwnd, NULL);
+    int id = -1;
+    for (int i = 0; i < MAX_PPTS; i++)
+    {
+        if (pptView[i].dwThreadId == windowThread)
+        {
+            id = i;
+            hook = pptView[id].hook;
+            break;
+        }
+    }
+    if ((id >= 0) && (nCode == HC_ACTION))
+    {
+        if (cwp->message == WM_USER + 22)
+        {
+            if (pptView[id].state != PPT_LOADED)
+            {
+                if ((pptView[id].currentSlide > 0)
+                    && (pptView[id].previewPath != NULL
+                    && strlen(pptView[id].previewPath) > 0))
+                {
+                    sprintf_s(filename, MAX_PATH, "%s%i.bmp", 
+                        pptView[id].previewPath, 
+                        pptView[id].currentSlide);
+                    CaptureAndSaveWindow(cwp->hwnd, filename);
+                }
+                if (((cwp->wParam == 0) 
+                    || (pptView[id].slideNos[1] == cwp->wParam))
+                    && (pptView[id].currentSlide > 0))
+                {
+                    pptView[id].state = PPT_LOADED;
+                    pptView[id].currentSlide = pptView[id].slideCount + 1;
+                } 
+                else 
+                {
+                    if (cwp->wParam > 0) 
+                    {
+                        pptView[id].currentSlide = pptView[id].currentSlide + 1;
+                        pptView[id].slideNos[pptView[id].currentSlide] 
+                            = cwp->wParam;
+                        pptView[id].slideCount = pptView[id].currentSlide;
+                        pptView[id].lastSlideSteps = 0;
+                    }
+                }
+            }
+            else
+            {
+                if (cwp->wParam > 0) 
+                {
+                    if(pptView[id].guess > 0 
+                        && pptView[id].slideNos[pptView[id].guess] == 0)
+                    {
+                        pptView[id].currentSlide = 0;
+                    }
+                    for(int i = 1; i <= pptView[id].slideCount; i++)
+                    {
+                        if(pptView[id].slideNos[i] == cwp->wParam)
+                        {
+                            pptView[id].currentSlide = i;
+                            break;
+                        }
+                    }
+                    if(pptView[id].currentSlide == 0)
+                    {
+                        pptView[id].slideNos[pptView[id].guess] = cwp->wParam;
+                        pptView[id].currentSlide = pptView[id].guess;
+                    }
+                    pptView[id].guess = 0;
+                } 
+            }
+        }
+        if ((pptView[id].state != PPT_CLOSED)
+
+            &&(cwp->message == WM_CLOSE || cwp->message == WM_QUIT))
+        {
+            pptView[id].state = PPT_CLOSING;
+        }
+    }
+    return CallNextHookEx(hook, nCode, wParam, lParam); 
 }
 
 VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename)
 {
-	HBITMAP hBmp;
-	if ((hBmp = CaptureWindow(hWnd)) == NULL) 
-		return;
-
-	RECT client;
-	GetClientRect (hWnd, &client);
-	UINT uiBytesPerRow = 3 * client.right; // RGB takes 24 bits
-	UINT uiRemainderForPadding;
-
-	if ((uiRemainderForPadding = uiBytesPerRow % sizeof (DWORD)) > 0) 
-		uiBytesPerRow += (sizeof (DWORD) - uiRemainderForPadding);
-
-	UINT uiBytesPerAllRows = uiBytesPerRow * client.bottom;
-	PBYTE pDataBits;
-
-	if ((pDataBits = new BYTE [uiBytesPerAllRows]) != NULL) 
-	{
-		BITMAPINFOHEADER bmi = {0};
-		BITMAPFILEHEADER bmf = {0};
-
-		// Prepare to get the data out of HBITMAP:
-		bmi.biSize = sizeof (bmi);
-		bmi.biPlanes = 1;
-		bmi.biBitCount = 24;
-		bmi.biHeight = client.bottom;
-		bmi.biWidth = client.right;
-
-		// Get it:
-		HDC hDC = GetDC (hWnd);
-		GetDIBits (hDC, hBmp, 0, client.bottom, pDataBits, 
-					(BITMAPINFO*) &bmi, DIB_RGB_COLORS);
-		ReleaseDC (hWnd, hDC);
-
-		// Fill the file header:
-		bmf.bfOffBits = sizeof (bmf) + sizeof (bmi);
-		bmf.bfSize = bmf.bfOffBits + uiBytesPerAllRows;
-		bmf.bfType = 0x4D42;
-
-		// Writing:
-		FILE* pFile;
-		int err = fopen_s(&pFile, filename, "wb");
-		if (err == 0) 
-		{
-			fwrite (&bmf, sizeof (bmf), 1, pFile);
-			fwrite (&bmi, sizeof (bmi), 1, pFile);
-			fwrite (pDataBits, sizeof (BYTE), uiBytesPerAllRows, pFile);
-			fclose (pFile);
-		} 
-		delete [] pDataBits;
-	}
-	DeleteObject (hBmp);
+    HBITMAP hBmp;
+    if ((hBmp = CaptureWindow(hWnd)) == NULL) 
+    {
+        return;
+    }
+    RECT client;
+    GetClientRect(hWnd, &client);
+    UINT uiBytesPerRow = 3 * client.right; // RGB takes 24 bits
+    UINT uiRemainderForPadding;
+
+    if ((uiRemainderForPadding = uiBytesPerRow % sizeof(DWORD)) > 0) 
+        uiBytesPerRow += (sizeof(DWORD) - uiRemainderForPadding);
+
+    UINT uiBytesPerAllRows = uiBytesPerRow * client.bottom;
+    PBYTE pDataBits;
+
+    if ((pDataBits = new BYTE[uiBytesPerAllRows]) != NULL) 
+    {
+        BITMAPINFOHEADER bmi = {0};
+        BITMAPFILEHEADER bmf = {0};
+
+        // Prepare to get the data out of HBITMAP:
+        bmi.biSize = sizeof(bmi);
+        bmi.biPlanes = 1;
+        bmi.biBitCount = 24;
+        bmi.biHeight = client.bottom;
+        bmi.biWidth = client.right;
+
+        // Get it:
+        HDC hDC = GetDC(hWnd);
+        GetDIBits(hDC, hBmp, 0, client.bottom, pDataBits, (BITMAPINFO*) &bmi,
+            DIB_RGB_COLORS);
+        ReleaseDC(hWnd, hDC);
+
+        // Fill the file header:
+        bmf.bfOffBits = sizeof(bmf) + sizeof(bmi);
+        bmf.bfSize = bmf.bfOffBits + uiBytesPerAllRows;
+        bmf.bfType = 0x4D42;
+
+        // Writing:
+        FILE* pFile;
+        int err = fopen_s(&pFile, filename, "wb");
+        if (err == 0) 
+        {
+            fwrite(&bmf, sizeof(bmf), 1, pFile);
+            fwrite(&bmi, sizeof(bmi), 1, pFile);
+            fwrite(pDataBits, sizeof(BYTE), uiBytesPerAllRows, pFile);
+            fclose(pFile);
+        } 
+        delete [] pDataBits;
+    }
+    DeleteObject(hBmp);
 }
-HBITMAP CaptureWindow (HWND hWnd) {
-	HDC hDC;
-	BOOL bOk = FALSE;
-	HBITMAP hImage = NULL;
-
-	hDC = GetDC (hWnd);
-	RECT rcClient;
-	GetClientRect (hWnd, &rcClient);
-	if ((hImage = CreateCompatibleBitmap (hDC, rcClient.right, rcClient.bottom)) != NULL) 
-	{
-		HDC hMemDC;
-		HBITMAP hDCBmp;
-
-		if ((hMemDC = CreateCompatibleDC (hDC)) != NULL) 
-		{
-			hDCBmp = (HBITMAP) SelectObject (hMemDC, hImage);
-			HMODULE hLib = LoadLibrary("User32");
-			// PrintWindow works for windows outside displayable area
-			// but was only introduced in WinXP. BitBlt requires the window to be topmost 
-			// and within the viewable area of the display
-			if(GetProcAddress(hLib, "PrintWindow")==NULL)
-			{
-				SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); 
-				BitBlt (hMemDC, 0, 0, rcClient.right, rcClient.bottom, hDC, 0, 0, SRCCOPY);
-				SetWindowPos(hWnd, HWND_NOTOPMOST, -32000, -32000, 0, 0, SWP_NOSIZE); 
-			}
-			else
-			{
-				PrintWindow(hWnd, hMemDC, 0);
-			}
-			SelectObject (hMemDC, hDCBmp);
-			DeleteDC (hMemDC);
-			bOk = TRUE;
-		}
-	}
-	ReleaseDC (hWnd, hDC);
-	if (! bOk) 
-	{
-		if (hImage) 
-		{
-			DeleteObject (hImage);
-			hImage = NULL;
-		}
-	}
-	return hImage;
+HBITMAP CaptureWindow(HWND hWnd)
+{
+    HDC hDC;
+    BOOL bOk = FALSE;
+    HBITMAP hImage = NULL;
+
+    hDC = GetDC(hWnd);
+    RECT rcClient;
+    GetClientRect(hWnd, &rcClient);
+    if ((hImage = CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom))
+        != NULL) 
+    {
+        HDC hMemDC;
+        HBITMAP hDCBmp;
+
+        if ((hMemDC = CreateCompatibleDC(hDC)) != NULL) 
+        {
+            hDCBmp = (HBITMAP)SelectObject(hMemDC, hImage);
+            HMODULE hLib = LoadLibrary("User32");
+            // PrintWindow works for windows outside displayable area
+            // but was only introduced in WinXP. BitBlt requires the window to  
+            // be topmost and within the viewable area of the display
+            if (GetProcAddress(hLib, "PrintWindow") == NULL)
+            {
+                SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); 
+                BitBlt(hMemDC, 0, 0, rcClient.right, rcClient.bottom, hDC, 0, 
+                    0, SRCCOPY);
+                SetWindowPos(hWnd, HWND_NOTOPMOST, -32000, -32000, 0, 0, 
+                    SWP_NOSIZE); 
+            }
+            else
+            {
+                PrintWindow(hWnd, hMemDC, 0);
+            }
+            SelectObject(hMemDC, hDCBmp);
+            DeleteDC(hMemDC);
+            bOk = TRUE;
+        }
+    }
+    ReleaseDC(hWnd, hDC);
+    if (!bOk) 
+    {
+        if (hImage) 
+        {
+            DeleteObject(hImage);
+            hImage = NULL;
+        }
+    }
+    return hImage;
 }

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/pptviewlib.dll'
Binary files openlp/plugins/presentations/lib/pptviewlib/pptviewlib.dll	2011-03-15 07:34:04 +0000 and openlp/plugins/presentations/lib/pptviewlib/pptviewlib.dll	2011-03-16 23:40:57 +0000 differ
=== modified file 'openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h'
--- openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h	2011-03-15 07:34:04 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h	2011-03-16 23:40:57 +0000
@@ -1,55 +1,84 @@
+/******************************************************************************
+* PptViewLib - PowerPoint Viewer 2003/2007 Controller                         *
+* OpenLP - Open Source Lyrics Projection                                      *
+* --------------------------------------------------------------------------- *
+* Copyright (c) 2008-2011 Raoul Snyman                                        *
+* Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      *
+* Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat,  *
+* Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon  *
+* Tibble, Carsten Tinggaard, Frode Woldsund                                   *
+* --------------------------------------------------------------------------- *
+* This program is free software; you can redistribute it and/or modify it     *
+* under the terms of the GNU General Public License as published by the Free  *
+* Software Foundation; version 2 of the License.                              *
+*                                                                             *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
+* more details.                                                               *
+*                                                                             *
+* You should have received a copy of the GNU General Public License along     *
+* with this program; if not, write to the Free Software Foundation, Inc., 59  *
+* Temple Place, Suite 330, Boston, MA 02111-1307 USA                          *
+******************************************************************************/
 
 #define DllExport extern "C"  __declspec( dllexport ) 
 
-enum PPTVIEWSTATE { PPT_CLOSED, PPT_STARTED, PPT_OPENED, PPT_LOADED, PPT_CLOSING};
-
-DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, char *previewpath);
+#define DEBUG(...)  if (debug) printf(__VA_ARGS__)
+
+enum PPTVIEWSTATE {PPT_CLOSED, PPT_STARTED, PPT_OPENED, PPT_LOADED, 
+    PPT_CLOSING};
+
+DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, 
+    char *previewPath);
 DllExport BOOL CheckInstalled();
 DllExport void ClosePPT(int id);
 DllExport int GetCurrentSlide(int id);
 DllExport int GetSlideCount(int id);
 DllExport void NextStep(int id);
 DllExport void PrevStep(int id);
-DllExport void GotoSlide(int id, int slideno);
+DllExport void GotoSlide(int id, int slide_no);
 DllExport void RestartShow(int id);
 DllExport void Blank(int id);
 DllExport void Unblank(int id);
 DllExport void Stop(int id);
 DllExport void Resume(int id);
-DllExport void SetDebug(BOOL onoff);
+DllExport void SetDebug(BOOL onOff);
 
 LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam);
 LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam);
 LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
-BOOL GetPPTViewerPath(char *pptviewerpath, int strsize);
-HBITMAP CaptureWindow (HWND hWnd);
-VOID SaveBitmap (CHAR* filename, HBITMAP hBmp) ;
+BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize);
+HBITMAP CaptureWindow(HWND hWnd);
+VOID SaveBitmap(CHAR* filename, HBITMAP hBmp) ;
 VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename);
 BOOL GetPPTInfo(int id);
 BOOL SavePPTInfo(int id);
-
-
 void Unhook(int id);
 
-#define MAX_PPTOBJS 50
+#define MAX_PPTS 16
+#define MAX_SLIDES 256
 
-struct PPTVIEWOBJ 
+struct PPTVIEW 
 {
-	HHOOK hook;
-	HHOOK mhook;
-	HWND hWnd;
-	HWND hWnd2;
-	HWND hParentWnd;
-	HANDLE hProcess;
-	HANDLE hThread;
-	DWORD dwProcessId;
-	DWORD dwThreadId;
-	RECT rect;
-	int slideCount;
-	int currentSlide;
-	int firstSlideSteps;
-	int steps;
-	char filename[MAX_PATH];
-	char previewpath[MAX_PATH];
-	PPTVIEWSTATE state;
+    HHOOK hook;
+    HHOOK msgHook;
+    HWND hWnd;
+    HWND hWnd2;
+    HWND hParentWnd;
+    HANDLE hProcess;
+    HANDLE hThread;
+    DWORD dwProcessId;
+    DWORD dwThreadId;
+    RECT rect;
+    int slideCount;
+    int currentSlide;
+    int firstSlideSteps;
+    int lastSlideSteps;
+    int steps;
+    int guess;
+    char filename[MAX_PATH];
+    char previewPath[MAX_PATH];
+    int slideNos[MAX_SLIDES];
+    PPTVIEWSTATE state;
 };


Follow ups