[Libreoffice-commits] online.git: Branch 'distro/collabora/milestone-5' - 16 commits - loleaflet/Makefile loleaflet/README loleaflet/reference.html loleaflet/src loolwsd/bundled loolwsd/LOKitClient.cpp loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/Makefile.am loolwsd/protocol.txt loolwsd/TileCache.cpp

Mihai Varga mihai.varga at collabora.com
Thu Oct 8 06:42:43 PDT 2015


 loleaflet/Makefile                                           |    2 
 loleaflet/README                                             |    3 
 loleaflet/reference.html                                     |   25 ++
 loleaflet/src/control/Parts.js                               |   19 ++
 loleaflet/src/core/Socket.js                                 |    1 
 loleaflet/src/layer/tile/GridLayer.js                        |   28 +++
 loleaflet/src/layer/tile/TileLayer.js                        |   96 ++++++++++-
 loleaflet/src/map/handler/Map.Keyboard.js                    |   70 +++++++-
 loleaflet/src/map/handler/Map.Mouse.js                       |   33 ++-
 loolwsd/LOKitClient.cpp                                      |    6 
 loolwsd/LOOLSession.cpp                                      |   54 +++++-
 loolwsd/LOOLSession.hpp                                      |    6 
 loolwsd/Makefile.am                                          |    4 
 loolwsd/TileCache.cpp                                        |    2 
 loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h      |   29 ++-
 loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h |    4 
 loolwsd/protocol.txt                                         |    7 
 17 files changed, 360 insertions(+), 29 deletions(-)

New commits:
commit 4fa63063d2dc957fd830cb3f27356a83e7fc985c
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 8 16:40:19 2015 +0300

    loleaflet: bump version after tarball

diff --git a/loleaflet/Makefile b/loleaflet/Makefile
index 444fc81..a77191f 100644
--- a/loleaflet/Makefile
+++ b/loleaflet/Makefile
@@ -3,7 +3,7 @@
 # ("micro") part: Between releases odd, even for releases (no other
 # changes inbetween).
 
-VERSION=1.2.6
+VERSION=1.2.7
 
 # Version number of the bundled 'draw' thing
 DRAW_VERSION=0.2.4
commit b433d066ce3f01b5e6ee28d60a4227771efc608c
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Thu Oct 8 16:39:47 2015 +0300

    loleaflet: bump version before tarball

diff --git a/loleaflet/Makefile b/loleaflet/Makefile
index aa96ef8..444fc81 100644
--- a/loleaflet/Makefile
+++ b/loleaflet/Makefile
@@ -3,7 +3,7 @@
 # ("micro") part: Between releases odd, even for releases (no other
 # changes inbetween).
 
-VERSION=1.2.5
+VERSION=1.2.6
 
 # Version number of the bundled 'draw' thing
 DRAW_VERSION=0.2.4
commit 1cf0c7299236734fc07950fac4fe5c2f145ab3de
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Tue Oct 6 17:33:22 2015 +0300

    handle LOK_CALLBACK_SEARCH_RESULT_SELECTION callback

diff --git a/loleaflet/reference.html b/loleaflet/reference.html
index d45f019..057c2d5 100644
--- a/loleaflet/reference.html
+++ b/loleaflet/reference.html
@@ -6823,6 +6823,11 @@ map.addControl(new MyControl());
 		<td><code>Number</code></td>
 		<td>Number of search results</td>
 	</tr>
+	<tr>
+		<td><code><b>results</b></code></td>
+		<td><code><a href="#bounds">Bounds[]</a></code></td>
+		<td>An array of bounds representing the selections of the search results in the document.</td>
+	</tr>
 </table>
 
 <h3 id="partpagerectangles-event">PartPageRectangles</h3>
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 5eaab4d..6be61de 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -214,8 +214,8 @@ L.TileLayer = L.GridLayer.extend({
 		else if (textMsg.startsWith('searchnotfound:')) {
 			this._onSearchNotFoundMsg(textMsg);
 		}
-		else if (textMsg.startsWith('searchresultcount:')) {
-			this._onSearchResultCount(textMsg);
+		else if (textMsg.startsWith('searchresultselection:')) {
+			this._onSearchResultSelection(textMsg);
 		}
 		else if (textMsg.startsWith('setpart:')) {
 			this._onSetPartMsg(textMsg);
@@ -336,11 +336,16 @@ L.TileLayer = L.GridLayer.extend({
 		this._map.fire('search', {originalPhrase: originalPhrase, count: 0});
 	},
 
-	_onSearchResultCount: function (textMsg) {
-		textMsg = textMsg.substring(19);
-		var count = parseInt(textMsg.substring(0, textMsg.indexOf(';')));
-		var originalPhrase = textMsg.substring(textMsg.indexOf(';') + 1);
-		this._map.fire('search', {originalPhrase: originalPhrase, count: count});
+	_onSearchResultSelection: function (textMsg) {
+		textMsg = textMsg.substring(23);
+		var obj = JSON.parse(textMsg);
+		var originalPhrase = obj.searchString;
+		var count = obj.searchResultSelection.length;
+		var results = [];
+		for (var i = 0; i < obj.searchResultSelection.length; i++) {
+			results.push(this._twipsRectangleToPixelBounds(obj.searchResultSelection[i]));
+		}
+		this._map.fire('search', {originalPhrase: originalPhrase, count: count, results: results});
 	},
 
 	_onStateChangedMsg: function (textMsg) {
diff --git a/loolwsd/LOKitClient.cpp b/loolwsd/LOKitClient.cpp
index 57f0e03..8e3f546 100644
--- a/loolwsd/LOKitClient.cpp
+++ b/loolwsd/LOKitClient.cpp
@@ -58,6 +58,7 @@ extern "C"
             CASE(STATUS_INDICATOR_FINISH);
             CASE(SEARCH_NOT_FOUND);
             CASE(SEARCH_RESULT_COUNT);
+            CASE(SEARCH_RESULT_SELECTION);
             CASE(DOCUMENT_SIZE_CHANGED);
             CASE(SET_PART);
 #undef CASE
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index ef1f1d8..d8b7dd0 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -826,6 +826,9 @@ extern "C"
         case LOK_CALLBACK_SEARCH_NOT_FOUND:
             srv->sendTextFrame("searchnotfound: " + std::string(pPayload));
             break;
+        case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+            srv->sendTextFrame("searchresultselection: " + std::string(pPayload));
+            break;
         case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
             srv->getStatus("", 0);
             srv->getPartPageRectangles("", 0);
commit 68398735302d6866461f52f948a09351d6a2b879
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Tue Oct 6 17:32:39 2015 +0300

    loleaflet: twips rectangle to pixel bounds method

diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js
index 9c89f7c..0e1fded 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -758,6 +758,21 @@ L.GridLayer = L.Layer.extend({
 				pixels.y * this._tileHeightTwips / this._tileSize);
 	},
 
+	_twipsRectangleToPixelBounds: function (strRectangle) {
+		// TODO use this more
+		// strRectangle = x, y, width, height
+		var strTwips = strRectangle.match(/\d+/g);
+		if (!strTwips) {
+			return null;
+		}
+		var topLeftTwips = new L.Point(parseInt(strTwips[0]), parseInt(strTwips[1]));
+		var offset = new L.Point(parseInt(strTwips[2]), parseInt(strTwips[3]));
+		var bottomRightTwips = topLeftTwips.add(offset);
+		return new L.Bounds(
+				this._twipsToPixels(topLeftTwips),
+				this._twipsToPixels(bottomRightTwips));
+	},
+
 	_noTilesToLoad: function () {
 		for (var key in this._tiles) {
 			if (!this._tiles[key].loaded) { return false; }
commit be67ec80650293c40135e63eeaf518aacd5c7134
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Oct 5 20:02:35 2015 +0300

    loleaflet: some ctrl+key shortcuts #tdf94608

diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js
index 98c722d..93490e4 100644
--- a/loleaflet/src/map/handler/Map.Keyboard.js
+++ b/loleaflet/src/map/handler/Map.Keyboard.js
@@ -187,10 +187,7 @@ L.Map.Keyboard = L.Handler.extend({
 		var alt = e.originalEvent.altKey ? this.keyModifier.alt : 0;
 		this.modifier = shift | ctrl | alt;
 		if (e.originalEvent.ctrlKey) {
-			// we prepare for a copy event
-			docLayer._textArea.value = 'dummy text';
-			docLayer._textArea.focus();
-			docLayer._textArea.select();
+			this._handleCtrlCommand(e);
 			return;
 		}
 
@@ -244,6 +241,65 @@ L.Map.Keyboard = L.Handler.extend({
 			}
 		}
 		L.DomEvent.stopPropagation(e.originalEvent);
+	},
+
+	_handleCtrlCommand: function (e) {
+		if (e.type !== 'keydown') {
+			e.originalEvent.preventDefault();
+			return;
+		};
+
+		switch (e.originalEvent.keyCode) {
+			case 13: // enter
+				L.Socket.sendMessage('uno .uno:InsertPagebreak');
+				break;
+			case 37: // left arrow
+				L.Socket.sendMessage('uno .uno:GoToPrevWord');
+				break;
+			case 39: // right arrow
+				L.Socket.sendMessage('uno .uno:GoToNextWord');
+				break;
+			case 65: // a
+				L.Socket.sendMessage('uno .uno:Selectall');
+				break;
+			case 66: // b
+				L.Socket.sendMessage('uno .uno:Bold');
+				break;
+			case 67: // c
+				// we prepare for a copy event
+				this._map._docLayer._textArea.value = 'dummy text';
+				this._map._docLayer._textArea.focus();
+				this._map._docLayer._textArea.select();
+				break;
+			case 69: // e
+				L.Socket.sendMessage('uno .uno:CenterPara');
+				break;
+			case 73: // i
+				L.Socket.sendMessage('uno .uno:Italic');
+				break;
+			case 74: // j
+				L.Socket.sendMessage('uno .uno:JustifyPara');
+				break;
+			case 76: // l
+				L.Socket.sendMessage('uno .uno:LeftPara');
+				break;
+			case 82: // r
+				L.Socket.sendMessage('uno .uno:RightPara');
+				break;
+			case 85: // u
+				L.Socket.sendMessage('uno .uno:Underline');
+				break;
+			case 90: // z
+				L.Socket.sendMessage('uno .uno:Undo');
+				break;
+			case 189: // -
+				L.Socket.sendMessage('uno .uno:InsertSoftHyphen');
+				break;
+		}
+		if (e.originalEvent.keyCode !== 67 && e.originalEvent.keyCode !== 86) {
+			// not copy or paste
+			e.originalEvent.preventDefault();
+		}
 	}
 });
 
commit f68c3907477ffd4829b0216f75db72d872fae60d
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Oct 5 16:44:40 2015 +0300

    search result count callback handler

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index cfe686a..5eaab4d 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -214,6 +214,9 @@ L.TileLayer = L.GridLayer.extend({
 		else if (textMsg.startsWith('searchnotfound:')) {
 			this._onSearchNotFoundMsg(textMsg);
 		}
+		else if (textMsg.startsWith('searchresultcount:')) {
+			this._onSearchResultCount(textMsg);
+		}
 		else if (textMsg.startsWith('setpart:')) {
 			this._onSetPartMsg(textMsg);
 		}
@@ -333,6 +336,13 @@ L.TileLayer = L.GridLayer.extend({
 		this._map.fire('search', {originalPhrase: originalPhrase, count: 0});
 	},
 
+	_onSearchResultCount: function (textMsg) {
+		textMsg = textMsg.substring(19);
+		var count = parseInt(textMsg.substring(0, textMsg.indexOf(';')));
+		var originalPhrase = textMsg.substring(textMsg.indexOf(';') + 1);
+		this._map.fire('search', {originalPhrase: originalPhrase, count: count});
+	},
+
 	_onStateChangedMsg: function (textMsg) {
 		var unoMsg = textMsg.substr(14).split('=');
 		var commandName = '',
diff --git a/loolwsd/LOKitClient.cpp b/loolwsd/LOKitClient.cpp
index 97d42da..57f0e03 100644
--- a/loolwsd/LOKitClient.cpp
+++ b/loolwsd/LOKitClient.cpp
@@ -57,6 +57,7 @@ extern "C"
             CASE(STATUS_INDICATOR_SET_VALUE);
             CASE(STATUS_INDICATOR_FINISH);
             CASE(SEARCH_NOT_FOUND);
+            CASE(SEARCH_RESULT_COUNT);
             CASE(DOCUMENT_SIZE_CHANGED);
             CASE(SET_PART);
 #undef CASE
@@ -117,7 +118,7 @@ protected:
 
             if (tokens[0] == "?" || tokens[0] == "help")
             {
-                std::cout << 
+                std::cout <<
                     "Commands mimic LOOL protocol but we talk directly to LOKit:" << std::endl <<
                     "    status" << std::endl <<
                     "        calls LibreOfficeKitDocument::getDocumentType, getParts, getPartName, getDocumentSize" << std::endl <<
@@ -152,7 +153,7 @@ protected:
                 int tilePosY(std::stoi(tokens[5]));
                 int tileWidth(std::stoi(tokens[6]));
                 int tileHeight(std::stoi(tokens[7]));
-                
+
                 std::vector<unsigned char> pixmap(canvasWidth*canvasHeight*4);
                 loKitDocument->pClass->setPart(loKitDocument, partNumber);
                 loKitDocument->pClass->paintTile(loKitDocument, pixmap.data(), canvasWidth, canvasHeight, tilePosX, tilePosY, tileWidth, tileHeight);
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index a293cde..ef1f1d8 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -808,6 +808,9 @@ extern "C"
         case LOK_CALLBACK_HYPERLINK_CLICKED:
             srv->sendTextFrame("hyperlinkclicked: " + std::string(pPayload));
             break;
+        case LOK_CALLBACK_SEARCH_RESULT_COUNT:
+            srv->sendTextFrame("searchresultcount: " + std::string(pPayload));
+            break;
         case LOK_CALLBACK_STATE_CHANGED:
             srv->sendTextFrame("statechanged: " + std::string(pPayload));
             break;
diff --git a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 7038e5f..dc3e0f9 100644
--- a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -155,7 +155,9 @@ typedef enum
      *
      * Payload is a single 0-based integer.
      */
-    LOK_CALLBACK_SET_PART
+    LOK_CALLBACK_SET_PART,
+    /// Number of search results, in case something is found.
+    LOK_CALLBACK_SEARCH_RESULT_COUNT
 }
 LibreOfficeKitCallbackType;
 
commit f3af51450ac43c16594d04a9bbb49391a6a493b9
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Oct 5 15:04:19 2015 +0300

    We now send the mouse button that has been pressed and also they key
    modifiers for actions such as ctrl+click or shift+click

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 86d7f2b..cfe686a 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -191,6 +191,9 @@ L.TileLayer = L.GridLayer.extend({
 		else if (textMsg.startsWith('graphicselection:')) {
 			this._onGraphicSelectionMsg(textMsg);
 		}
+		else if (textMsg.startsWith('hyperlinkclicked:')) {
+			this._onHyperlinkClickedMsg(textMsg);
+		}
 		else if (textMsg.startsWith('invalidatecursor:')) {
 			this._onInvalidateCursorMsg(textMsg);
 		}
@@ -280,6 +283,11 @@ L.TileLayer = L.GridLayer.extend({
 		this._onUpdateGraphicSelection();
 	},
 
+	_onHyperlinkClickedMsg: function (textMsg) {
+		var link = textMsg.substring(18);
+		window.open(link, '_blank');
+	},
+
 	_onInvalidateCursorMsg: function (textMsg) {
 		var strTwips = textMsg.match(/\d+/g);
 		var topLeftTwips = new L.Point(parseInt(strTwips[0]), parseInt(strTwips[1]));
@@ -503,9 +511,10 @@ L.TileLayer = L.GridLayer.extend({
 		this._onUpdateGraphicSelection();
 	},
 
-	_postMouseEvent: function(type, x, y, count) {
+	_postMouseEvent: function(type, x, y, count, buttons, modifier) {
 		L.Socket.sendMessage('mouse type=' + type +
-				' x=' + x + ' y=' + y + ' count=' + count);
+				' x=' + x + ' y=' + y + ' count=' + count +
+				' buttons=' + buttons + ' modifier=' + modifier);
 	},
 
 	_postKeyboardEvent: function(type, charcode, keycode) {
diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js
index 987d2b4..98c722d 100644
--- a/loleaflet/src/map/handler/Map.Keyboard.js
+++ b/loleaflet/src/map/handler/Map.Keyboard.js
@@ -115,6 +115,7 @@ L.Map.Keyboard = L.Handler.extend({
 		this._map = map;
 		this._setPanOffset(map.options.keyboardPanOffset);
 		this._setZoomOffset(map.options.keyboardZoomOffset);
+		this.modifier = 0;
 	},
 
 	addHooks: function () {
@@ -180,6 +181,11 @@ L.Map.Keyboard = L.Handler.extend({
 
 	_onKeyDown: function (e) {
 		var docLayer = this._map._docLayer;
+		this.modifier = 0;
+		var shift = e.originalEvent.shiftKey ? this.keyModifier.shift : 0;
+		var ctrl = e.originalEvent.ctrlKey ? this.keyModifier.ctrl : 0;
+		var alt = e.originalEvent.altKey ? this.keyModifier.alt : 0;
+		this.modifier = shift | ctrl | alt;
 		if (e.originalEvent.ctrlKey) {
 			// we prepare for a copy event
 			docLayer._textArea.value = 'dummy text';
diff --git a/loleaflet/src/map/handler/Map.Mouse.js b/loleaflet/src/map/handler/Map.Mouse.js
index ac731a8..9fd8ba8 100644
--- a/loleaflet/src/map/handler/Map.Mouse.js
+++ b/loleaflet/src/map/handler/Map.Mouse.js
@@ -23,6 +23,18 @@ L.Map.Mouse = L.Handler.extend({
 			this._onMouseEvent, this);
 	},
 
+	LOButtons: {
+		left: 1,
+		middle: 2,
+		right: 4
+	},
+
+	JSButtons: {
+		left: 0,
+		middle: 1,
+		right: 2
+	},
+
 	_onMouseEvent: function (e) {
 		var docLayer = this._map._docLayer;
 		if (!docLayer) {
@@ -39,6 +51,12 @@ L.Map.Mouse = L.Handler.extend({
 			}
 		}
 
+		var modifier = this._map.keyboard.modifier;
+		var buttons = 0;
+		buttons |= e.originalEvent.button === this.JSButtons.left ? this.LOButtons.left : 0;
+		buttons |= e.originalEvent.button === this.JSButtons.middle ? this.LOButtons.middle : 0;
+		buttons |= e.originalEvent.button === this.JSButtons.right ? this.LOButtons.right : 0;
+
 		if (e.type === 'mousedown') {
 			docLayer._resetPreFetching();
 			this._mouseDown = true;
@@ -47,7 +65,8 @@ L.Map.Mouse = L.Handler.extend({
 			}
 			var mousePos = docLayer._latLngToTwips(e.latlng);
 			this._mouseEventsQueue.push(L.bind(function() {
-				this._postMouseEvent('buttondown', mousePos.x, mousePos.y, 1);}, docLayer));
+				this._postMouseEvent('buttondown', mousePos.x, mousePos.y, 1, buttons, modifier);
+			}, docLayer));
 			this._holdMouseEvent = setTimeout(L.bind(this._executeMouseEvents, this), 500);
 		}
 		else if (e.type === 'mouseup') {
@@ -82,7 +101,7 @@ L.Map.Mouse = L.Handler.extend({
 						}
 					}
 					this._mouseEventsQueue = [];
-					docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 1);
+					docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 1, buttons, modifier);
 					docLayer._textArea.focus();
 				}, this));
 				this._holdMouseEvent = setTimeout(L.bind(this._executeMouseEvents, this), timeOut);
@@ -113,7 +132,7 @@ L.Map.Mouse = L.Handler.extend({
 			}
 			if (!this._map.dragging.enabled()) {
 				mousePos = docLayer._latLngToTwips(e.latlng);
-				docLayer._postMouseEvent('move', mousePos.x, mousePos.y, 1);
+				docLayer._postMouseEvent('move', mousePos.x, mousePos.y, 1, buttons, modifier);
 				for (key in docLayer._selectionHandles) {
 					handle = docLayer._selectionHandles[key];
 					if (handle._icon) {
@@ -124,10 +143,10 @@ L.Map.Mouse = L.Handler.extend({
 		}
 		else if (e.type === 'dblclick') {
 			mousePos = docLayer._latLngToTwips(e.latlng);
-			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 1);
-			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 2);
-			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 2);
-			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 1);
+			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 1, buttons, modifier);
+			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 2, buttons, modifier);
+			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 2, 1, buttons, modifier);
+			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 1, 1, buttons, modifier);
 		}
 	},
 
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 5f5d12e..a293cde 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -1025,9 +1025,9 @@ bool ChildProcessSession::keyEvent(const char *buffer, int length, StringTokeniz
 
 bool ChildProcessSession::mouseEvent(const char *buffer, int length, StringTokenizer& tokens)
 {
-    int type, x, y, count;
+    int type, x, y, count, buttons, modifier;
 
-    if (tokens.count() != 5 ||
+    if (tokens.count() != 7 ||
         !getTokenKeyword(tokens[1], "type",
                          {{"buttondown", LOK_MOUSEEVENT_MOUSEBUTTONDOWN},
                           {"buttonup", LOK_MOUSEEVENT_MOUSEBUTTONUP},
@@ -1035,13 +1035,15 @@ bool ChildProcessSession::mouseEvent(const char *buffer, int length, StringToken
                          type) ||
         !getTokenInteger(tokens[2], "x", x) ||
         !getTokenInteger(tokens[3], "y", y) ||
-        !getTokenInteger(tokens[4], "count", count))
+        !getTokenInteger(tokens[4], "count", count),
+        !getTokenInteger(tokens[5], "buttons", buttons),
+        !getTokenInteger(tokens[6], "modifier", modifier))
     {
         sendTextFrame("error: cmd=mouse kind=syntax");
         return false;
     }
 
-    _loKitDocument->pClass->postMouseEvent(_loKitDocument, type, x, y, count);
+    _loKitDocument->pClass->postMouseEvent(_loKitDocument, type, x, y, count, buttons, modifier);
 
     return true;
 }
diff --git a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
index d83dd49..83dcc98 100644
--- a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
@@ -137,7 +137,9 @@ struct _LibreOfficeKitDocumentClass
                             int nType,
                             int nX,
                             int nY,
-                            int nCount);
+                            int nCount,
+                            int nButtons,
+                            int nModifier);
 
     /// @see lok::Document::postUnoCommand
     void (*postUnoCommand) (LibreOfficeKitDocument* pThis,
commit d92c8903adb565d8ac4040cdacac4ad7b94d5099
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Wed Sep 30 17:22:00 2015 +0300

    loolwsd: update page sizes when the doc size changes

diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 313e76f..5f5d12e 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -825,6 +825,7 @@ extern "C"
             break;
         case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
             srv->getStatus("", 0);
+            srv->getPartPageRectangles("", 0);
             break;
         case LOK_CALLBACK_SET_PART:
             srv->sendTextFrame("setpart: " + std::string(pPayload));
commit 0557bc170a179393a6e237d0a596f8fdb98eafd2
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Wed Sep 30 17:17:03 2015 +0300

    loolwsd: switch to editing dir when invalidating the cursor

diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 4b00dea..313e76f 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -218,6 +218,9 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
             {
                 peer->_tileCache->saveTextFile(std::string(buffer, length), "partpagerectangles.txt");
             }
+            else if (tokens[0] == "invalidatecursor:") {
+                peer->_tileCache->setEditing(true);
+            }
             else if (tokens[0] == "invalidatetiles:")
             {
                 // FIXME temporarily, set the editing on the 1st invalidate, TODO extend
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 76ca730..cbd0278 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -172,7 +172,7 @@ void TileCache::setEditing(bool editing)
 
 void TileCache::saveTextFile(const std::string& text, std::string fileName)
 {
-    std::string dirName = cacheDirName(_hasUnsavedChanges);
+    std::string dirName = cacheDirName(_isEditing);
 
     File(dirName).createDirectories();
 
commit 0219c1877a8f6c6276ee8808f7e90264e4f7ec15
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Wed Sep 30 13:43:12 2015 +0300

    loleaflet: goToPage without having a LOK instance
    
    Knowing the page dimension, we can scroll to the desired page
    without requesting sending the 'setpage' command to the server

diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 1ae0825..d710d47 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -122,7 +122,19 @@ L.Map.include({
 		else if (typeof (page) === 'number' && page >= 0 && page < docLayer._pages) {
 			docLayer._currentPage = page;
 		}
-		L.Socket.sendMessage('setpage page=' + docLayer._currentPage);
+		if (docLayer._permission !== 'edit' && docLayer._partPageRectanglesPixels.length > docLayer._currentPage) {
+			// we can scroll to the desired page without having a LOK instance
+			var pageBounds = docLayer._partPageRectanglesPixels[docLayer._currentPage];
+			var pos = new L.Point(
+					pageBounds.min.x + (pageBounds.max.x - pageBounds.min.x) / 2,
+					pageBounds.min.y);
+			pos.y -= this.getSize().y / 4; // offset by a quater of the viewing area so that the previous page is visible
+			this.scrollTop(pos.y, {update: true});
+			this.scrollLeft(pos.x, {update: true});
+		}
+		else {
+			L.Socket.sendMessage('setpage page=' + docLayer._currentPage);
+		}
 		this.fire('pagenumberchanged', {
 			currentPage: docLayer._currentPage,
 			pages: docLayer._pages,
commit 771ae08cb682aa163b770ad736ad21d696bee259
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Wed Sep 30 13:17:43 2015 +0300

    loleaflet: partpagerectangles command integration
    
    An event is fired with the page dimensions.
    Also the current page number is updated based on which page contains
    the current view's center

diff --git a/loleaflet/README b/loleaflet/README
index 4a32d13..8cc2739 100644
--- a/loleaflet/README
+++ b/loleaflet/README
@@ -193,6 +193,9 @@ Writer pages:
             + e.docType = document type, should be 'text'
         map.on('invalidatepreview', function (e) {})
             + e.id = the preview's id
+        map.on('partpagerectangles', function (e) {}) where:
+            + e.pixelRectangles = An array of bounds representing each page's dimension in pixels on the current zoom level
+            + e.twipsRectangles = An array of bounds representing each page's dimension in twips.
 
 Error:
     - events
diff --git a/loleaflet/reference.html b/loleaflet/reference.html
index 595dd62..d45f019 100644
--- a/loleaflet/reference.html
+++ b/loleaflet/reference.html
@@ -6825,6 +6825,26 @@ map.addControl(new MyControl());
 	</tr>
 </table>
 
+<h3 id="partpagerectangles-event">PartPageRectangles</h3>
+
+<table data-id='events'>
+	<tr>
+		<th class="width100">property</th>
+		<th>type</th>
+		<th>description</th>
+	</tr>
+	<tr>
+		<td><code><b>pixelRectangles</b></code></td>
+        <td><code><a href="#bounds">Bounds[]</a></code></td>
+		<td>An array of bounds representing each page's dimension in pixels on the current zoom level.</td>
+	</tr>
+	<tr>
+		<td><code><b>twipsRectangles</b></code></td>
+		<td><code><a href="#bounds">Bounds[]</a></code></td>
+		<td>An array of bounds representing each page's dimension in twips.</td>
+	</tr>
+</table>
+
 <h3 id="permission-event">PermissionEvent</h3>
 
 <table data-id='events'>
diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 55d4c9b..1ae0825 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -123,6 +123,11 @@ L.Map.include({
 			docLayer._currentPage = page;
 		}
 		L.Socket.sendMessage('setpage page=' + docLayer._currentPage);
+		this.fire('pagenumberchanged', {
+			currentPage: docLayer._currentPage,
+			pages: docLayer._pages,
+			docType: docLayer._docType
+		});
 	},
 
 	getNumberOfPages: function () {
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index ba93c2b..99a8c19 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -52,6 +52,7 @@ L.Socket = {
 		}
 		this.socket.send(msg);
 		this.socket.send('status');
+		this.socket.send('partpagerectangles');
 		for (var i = 0; i < this._msgQueue.length; i++) {
 			this.socket.send(this._msgQueue[i].msg);
 			L.Log.log(this._msgQueue[i].msg, this._msgQueue[i].coords);
diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js
index 2922d7e..9c89f7c 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -444,6 +444,7 @@ L.GridLayer = L.Layer.extend({
 	_move: function () {
 		this._update();
 		this._resetPreFetching(true);
+		this._onCurrentPageUpdate();
 	},
 
 	_update: function (center, zoom) {
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 0bf5474..86d7f2b 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -102,6 +102,7 @@ L.TileLayer = L.GridLayer.extend({
 		map.on('drag resize zoomend', this._updateScrollOffset, this);
 		map.on('copy', this._onCopy, this);
 		map.on('zoomend', this._onUpdateCursor, this);
+		map.on('zoomend', this._onUpdatePartPageRectangles, this);
 		map.on('dragstart', this._onDragStart, this);
 		map.on('requestloksession', this._onRequestLOKSession, this);
 		map.on('error', this._mapOnError, this);
@@ -204,6 +205,9 @@ L.TileLayer = L.GridLayer.extend({
 			msg += 'height=' + this._docHeightTwips;
 			this._onInvalidateTilesMsg(msg);
 		}
+		else if (textMsg.startsWith('partpagerectangles:')) {
+			this._onPartPageRectanglesMsg(textMsg);
+		}
 		else if (textMsg.startsWith('searchnotfound:')) {
 			this._onSearchNotFoundMsg(textMsg);
 		}
@@ -288,6 +292,34 @@ L.TileLayer = L.GridLayer.extend({
 		this._onUpdateCursor();
 	},
 
+	_onPartPageRectanglesMsg: function (textMsg) {
+		textMsg = textMsg.substring(19);
+		var pages = textMsg.split(';');
+		this._partPageRectanglesTwips = [];
+		this._partPageRectanglesPixels = [];
+		for (var i = 0; i < pages.length; i++) {
+			var strTwips = pages[i].match(/\d+/g);
+			if (!strTwips) {
+				// probably not a text file
+				return;
+			}
+			var topLeftTwips = new L.Point(parseInt(strTwips[0]), parseInt(strTwips[1]));
+			var offset = new L.Point(parseInt(strTwips[2]), parseInt(strTwips[3]));
+			var bottomRightTwips = topLeftTwips.add(offset);
+			var pageBoundsTwips = new L.Bounds(topLeftTwips, bottomRightTwips);
+			this._partPageRectanglesTwips.push(pageBoundsTwips);
+			var pageBoundsPixels = new L.Bounds(
+					this._twipsToPixels(topLeftTwips),
+					this._twipsToPixels(bottomRightTwips));
+			this._partPageRectanglesPixels.push(pageBoundsPixels);
+		}
+		this._map.fire('partpagerectangles', {
+			pixelRectangles: this._partPageRectanglesPixels,
+			twipsRectangles: this._partPageRectanglesTwips
+		});
+		this._onCurrentPageUpdate();
+	},
+
 	_onSearchNotFoundMsg: function (textMsg) {
 		var originalPhrase = textMsg.substring(16);
 		this._map.fire('search', {originalPhrase: originalPhrase, count: 0});
@@ -689,6 +721,42 @@ L.TileLayer = L.GridLayer.extend({
 				this._map.setZoom(Math.min(10, this._map.getZoom() + zoomDelta), {animate: false});
 			}
 		}
+	},
+
+	_onCurrentPageUpdate: function () {
+		var mapCenter = this._map.project(this._map.getCenter());
+		if (!this._partPageRectanglesPixels || !(this._currentPage >= 0) ||
+				this._partPageRectanglesPixels[this._currentPage].contains(mapCenter)) {
+			// page number has not changed
+			return;
+		}
+		for (var i = 0; i < this._partPageRectanglesPixels.length; i++) {
+			if (this._partPageRectanglesPixels[i].contains(mapCenter)) {
+				this._currentPage = i;
+				this._map.fire('pagenumberchanged', {
+					currentPage: this._currentPage,
+					pages: this._pages,
+					docType: this._docType
+				});
+				return;
+			}
+		}
+	},
+
+	_onUpdatePartPageRectangles: function () {
+		if (this._partPageRectanglesPixels.length > 0) {
+			this._partPageRectanglesPixels = [];
+			for (var i = 0; i < this._partPageRectanglesTwips.length; i++) {
+				var pageBounds = new L.Bounds(
+						this._twipsToPixels(this._partPageRectanglesTwips[i].min),
+						this._twipsToPixels(this._partPageRectanglesTwips[i].max));
+				this._partPageRectanglesPixels.push(pageBounds);
+			}
+			this._map.fire('partpagerectangles', {
+				pixelRectangles: this._partPageRectanglesPixels,
+				twipsRectangles: this._partPageRectanglesTwips
+			});
+		}
 	}
 });
 
commit 32e89553b8a4a281d721e3a6b1fe7eb3300567ef
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Wed Sep 30 13:10:48 2015 +0300

    loleaflet: twipsToPixels and back methods

diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js
index e010aa3..2922d7e 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -745,6 +745,18 @@ L.GridLayer = L.Layer.extend({
 				Math.round(pixels.y / this._tileSize * this._tileHeightTwips));
 	},
 
+	_twipsToPixels: function (twips) {
+		return new L.Point(
+				twips.x / this._tileWidthTwips * this._tileSize,
+				twips.y / this._tileHeightTwips * this._tileSize);
+	},
+
+	_pixelsToTwips: function (pixels) {
+		return new L.Point(
+				pixels.x * this._tileWidthTwips / this._tileSize,
+				pixels.y * this._tileHeightTwips / this._tileSize);
+	},
+
 	_noTilesToLoad: function () {
 		for (var key in this._tiles) {
 			if (!this._tiles[key].loaded) { return false; }
commit afe2a71692bf4cfaf9f3c3e1c17b9e5b9cb0a979
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Sep 29 12:55:21 2015 +0200

    loolwsd: document partpagerectangles command on both directions

diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 369bb69..88cc062 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -75,6 +75,9 @@ uno <command>
 
     <command> is a line of text.
 
+partpagerectangles
+
+    Invokes lok::Document::getPartPageRectangles().
 
 server -> client
 ================
@@ -117,6 +120,10 @@ status: type=<typeName> parts=<numberOfParts> current=<currentPartNumber> width=
 
 styles: {"styleFamily": ["styles in family"], etc. }
 
+partpagerectangles: <payload>
+
+    Payload format is the same as LOK_CALLBACK_TEXT_SELECTION.
+
 textselectioncontent: <content>
 
     Current selection's content
commit c543d3d740be636caee43de1e72ba248e5503fce
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Sep 29 12:27:45 2015 +0200

    loolwsd: parse the partpagerectangles command and cache the values

diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 233e999..4b00dea 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -214,6 +214,10 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
                 std::string commandName = object->get("commandName").toString();
                 peer->_tileCache->saveTextFile(std::string(buffer, length), "cmdValues" + commandName + ".txt");
             }
+            else if (tokens[0] == "partpagerectangles:")
+            {
+                peer->_tileCache->saveTextFile(std::string(buffer, length), "partpagerectangles.txt");
+            }
             else if (tokens[0] == "invalidatetiles:")
             {
                 // FIXME temporarily, set the editing on the 1st invalidate, TODO extend
@@ -283,6 +287,7 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
     }
     else if (tokens[0] != "canceltiles" &&
              tokens[0] != "commandvalues" &&
+             tokens[0] != "partpagerectangles" &&
              tokens[0] != "gettextselection" &&
              tokens[0] != "invalidatetiles" &&
              tokens[0] != "key" &&
@@ -315,6 +320,10 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
     {
         return getCommandValues(buffer, length, tokens);
     }
+    else if (tokens[0] == "partpagerectangles")
+    {
+        return getPartPageRectangles(buffer, length);
+    }
     else if (tokens[0] == "invalidatetiles")
     {
         return invalidateTiles(buffer, length, tokens);
@@ -454,6 +463,21 @@ bool MasterProcessSession::getCommandValues(const char *buffer, int length, Stri
     return true;
 }
 
+bool MasterProcessSession::getPartPageRectangles(const char *buffer, int length)
+{
+    std::string partPageRectangles = _tileCache->getTextFile("partpagerectangles.txt");
+    if (partPageRectangles.size() > 0)
+    {
+        sendTextFrame(partPageRectangles);
+        return true;
+    }
+
+    if (_peer.expired())
+        dispatchChild();
+    forwardToPeer(buffer, length);
+    return true;
+}
+
 void MasterProcessSession::sendTile(const char *buffer, int length, StringTokenizer& tokens)
 {
     int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
@@ -633,6 +657,10 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
     {
         return getCommandValues(buffer, length, tokens);
     }
+    if (tokens[0] == "partpagerectangles")
+    {
+        return getPartPageRectangles(buffer, length);
+    }
     if (tokens[0] == "load")
     {
         if (_docURL != "")
@@ -895,6 +923,12 @@ bool ChildProcessSession::getCommandValues(const char *buffer, int length, Strin
     return true;
 }
 
+bool ChildProcessSession::getPartPageRectangles(const char* /*buffer*/, int /*length*/)
+{
+    sendTextFrame("partpagerectangles: " + std::string(_loKitDocument->pClass->getPartPageRectangles(_loKitDocument)));
+    return true;
+}
+
 void ChildProcessSession::sendTile(const char *buffer, int length, StringTokenizer& tokens)
 {
     int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index 247012c..13970c6 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -47,6 +47,8 @@ public:
 
     virtual bool getCommandValues(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0;
 
+    virtual bool getPartPageRectangles(const char *buffer, int length) = 0;
+
     virtual bool handleInput(const char *buffer, int length) = 0;
 
 protected:
@@ -113,6 +115,8 @@ public:
 
     virtual bool getCommandValues(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
+    virtual bool getPartPageRectangles(const char *buffer, int length) override;
+
  protected:
     bool invalidateTiles(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
@@ -161,6 +165,8 @@ public:
 
     virtual bool getCommandValues(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
+    virtual bool getPartPageRectangles(const char *buffer, int length) override;
+
     LibreOfficeKitDocument *_loKitDocument;
     std::string _docType;
 
commit d8a4499567712ae5dd9cda99e18ff5124404e05f
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Sep 29 12:27:27 2015 +0200

    loolwsd: update bundled LOK headers

diff --git a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
index 8060f0e..d83dd49 100644
--- a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
@@ -54,6 +54,9 @@ struct _LibreOfficeKitClass
     void (*registerCallback) (LibreOfficeKit* pThis,
                               LibreOfficeKitCallback pCallback,
                               void* pData);
+
+    /// @see lok::Office::getFilterTypes().
+    char* (*getFilterTypes) (LibreOfficeKit* pThis);
 #endif
 };
 
@@ -82,6 +85,9 @@ struct _LibreOfficeKitDocumentClass
     /// @see lok::Document::getParts().
     int (*getParts) (LibreOfficeKitDocument* pThis);
 
+    /// @see lok::Document::getPartPageRectangles().
+    char* (*getPartPageRectangles) (LibreOfficeKitDocument* pThis);
+
     /// @see lok::Document::getPart().
     int (*getPart) (LibreOfficeKitDocument* pThis);
 
@@ -93,10 +99,7 @@ struct _LibreOfficeKitDocumentClass
     char* (*getPartName) (LibreOfficeKitDocument* pThis,
                           int nPart);
 
-    /** Sets mode of the current part.
-     *
-     * @param nMode - element from the LibreOfficeKitPartMode enum.
-     */
+    /// @see lok::Document::setPartMode().
     void (*setPartMode) (LibreOfficeKitDocument* pThis,
                          int nMode);
 
@@ -118,6 +121,7 @@ struct _LibreOfficeKitDocumentClass
     /// @see lok::Document::initializeForRendering().
     void (*initializeForRendering) (LibreOfficeKitDocument* pThis);
 
+    /// @see lok::Document::registerCallback().
     void (*registerCallback) (LibreOfficeKitDocument* pThis,
                               LibreOfficeKitCallback pCallback,
                               void* pData);
@@ -160,8 +164,19 @@ struct _LibreOfficeKitDocumentClass
     /// @see lok::Document::resetSelection
     void (*resetSelection) (LibreOfficeKitDocument* pThis);
 
-    /// @see lok::Document:getStyles
+    /// @see lok::Document::getCommandValues().
     char* (*getCommandValues) (LibreOfficeKitDocument* pThis, const char* pCommand);
+
+    /// @see lok::Document::createView().
+    int (*createView) (LibreOfficeKitDocument* pThis);
+    /// @see lok::Document::destroyView().
+    void (*destroyView) (LibreOfficeKitDocument* pThis, int nId);
+    /// @see lok::Document::setView().
+    void (*setView) (LibreOfficeKitDocument* pThis, int nId);
+    /// @see lok::Document::getView().
+    int (*getView) (LibreOfficeKitDocument* pThis);
+    /// @see lok::Document::getViews().
+    int (*getViews) (LibreOfficeKitDocument* pThis);
 #endif // LOK_USE_UNSTABLE_API
 };
 
commit fdc739d85732ccec3b176c8cd279517b15dffb5b
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Sep 29 11:15:02 2015 +0200

    loolwsd: implement a 'make tags'

diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index 07b68ca..9e1f143 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -34,3 +34,7 @@ all-local: loolwsd
 		sudo chown root loolwsd && sudo chmod u+s loolwsd; \
 	    fi; \
 	fi
+
+tags:
+	ctags --c++-kinds=+p --fields=+iaS --extra=+q -R --totals=yes \
+		--exclude=jails *


More information about the Libreoffice-commits mailing list