summaryrefslogtreecommitdiffstats
path: root/kmousetool/kmousetool/mtstroke.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmousetool/kmousetool/mtstroke.cpp')
-rw-r--r--kmousetool/kmousetool/mtstroke.cpp288
1 files changed, 288 insertions, 0 deletions
diff --git a/kmousetool/kmousetool/mtstroke.cpp b/kmousetool/kmousetool/mtstroke.cpp
new file mode 100644
index 0000000..16b1078
--- /dev/null
+++ b/kmousetool/kmousetool/mtstroke.cpp
@@ -0,0 +1,288 @@
+/***************************************************************************
+ mtstroke.cpp - description
+ -------------------
+ begin : Fri Oct 11 2002
+ copyright : (C) 2002 by Jeff Roush
+ email : jeff@mousetool.com
+ copyright : (C) 2003 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "mtstroke.h"
+#include "kmousetool.h"
+#include <iostream>
+
+// these are for locating the stroke information file
+#include <kstandarddirs.h>
+#include <qstring.h>
+
+// #include <string>
+
+using namespace std;
+
+const int MTStroke::DontClick = -1;
+const int MTStroke::bumped_mouse = 0;
+const int MTStroke::normal = 1;
+const int MTStroke::RightClick = 2;
+const int MTStroke::DoubleClick = 3;
+const int MTStroke::circle = 4;
+const int MTStroke::LowerLeftStroke = 5;
+const int MTStroke::UpperRightStroke = 6;
+const int MTStroke::LowerRightStroke = 7;
+const int MTStroke::UpperLeftStroke = 8;
+
+int MTStroke::delta_xy = 10;
+
+const int MTStroke::min_num_points = 5;
+
+Pt MTStroke::LowerLeft (0,0);
+Pt MTStroke::LowerRight(0,0);
+Pt MTStroke::UpperLeft (0,0);
+Pt MTStroke::UpperRight(0,0);
+
+
+
+MTStroke::MTStroke(){
+ readSequence();
+}
+MTStroke::~MTStroke(){
+}
+
+// add the new point, but only if it's not the same as the previous point.
+void MTStroke::addPt(const int x, const int y)
+{
+ if (points.size()==0) {
+ points.push_back(Pt(x,y));
+ }
+ else {
+ Pt pt(x,y);
+ if (!pt.sameAs(points[points.size()-1])) {
+ points.push_back(Pt(x,y));
+ }
+ }
+}
+
+
+/*
+ * Loop over all the strokes;
+ * return true if the given point is included
+ */
+bool MTStroke::pointsContain(Pt pt)
+{
+ std::vector<Pt>::iterator pos;
+ for (pos=points.begin(); pos<points.end(); pos++) {
+ if (pt.x==pos->x && pt.y==pos->y)
+ return true;
+ }
+ return false;
+}
+
+int MTStroke::getStrokeType()
+{
+ int size = points.size();
+
+ // If the mouse moved just a bit, it was probably bumped. Don't click.
+ if (size<min_num_points)
+ return normal;
+// return bumped_mouse;
+
+ Pt lastPoint = points[points.size()-1];
+
+ // If the mouse is pausing in a corner, then the user is either in the middle of a
+ // stroke, or wants to rest the mouse. Don't click.
+ if (lastPoint.sameAs(LowerLeft) || lastPoint.sameAs(LowerRight)
+ || lastPoint.sameAs(UpperLeft) || lastPoint.sameAs(UpperRight))
+ return DontClick;
+
+ // If the mouse visited a corner...
+ if (pointsContain(LowerLeft)) {
+ reset();
+ return LowerLeftStroke;
+ }
+ if (pointsContain(UpperRight)) {
+ reset();
+ return UpperRightStroke;
+ }
+ scale();
+
+ std::map<std::string, int>::iterator keypos = sequenceMap.find(sequence);
+ if (keypos == sequenceMap.end()) {
+ reset();
+ return normal;
+ }
+ reset();
+// return RightClick;
+ return keypos->second;
+}
+
+void MTStroke::scale()
+{
+ getExtent();
+ int deltax = stroke_maxx - stroke_minx;
+ int deltay = stroke_maxy - stroke_miny;
+ int delta = max(deltax, deltay);
+ int scale = (int) delta/2;
+
+ std::vector<Pt>::iterator pos;
+ for (pos=points.begin(); pos<points.end(); pos++) {
+
+ // add an extra (scale/2) because the divide rounds _down_, and we want to
+ // round _up_ or _down_, depending on which is closer.
+ pos->x = (int) (pos->x-stroke_minx + scale/2)/scale;
+ pos->y = (int) (pos->y-stroke_miny + scale/2)/scale;
+
+ // now, get the integer representing this position and add it to the stroke sequence
+ int n = 3*pos->y + pos->x + 1;
+ int index = sequence.size()-1;
+ n += '0';
+ if (index==-1)
+ sequence += n;
+ else if (n!=sequence[index])
+ sequence += n;
+ }
+}
+
+int MTStroke::max(int n, int m)
+{
+ if (n>m)
+ return n;
+ return m;
+}
+
+
+/*
+ * Find the bounding rectangle for the stroke
+ */
+void MTStroke::getExtent()
+{
+ stroke_minx = UpperRight.x;
+ stroke_maxx = 0;
+ stroke_miny = LowerLeft.y;
+ stroke_maxy = 0;
+
+ std::vector<Pt>::iterator pos;
+ for (pos=points.begin(); pos<points.end(); pos++) {
+ if (stroke_minx > pos->x)
+ stroke_minx = pos->x;
+ if (stroke_maxx < pos->x)
+ stroke_maxx = pos->x;
+ if (stroke_miny > pos->y)
+ stroke_miny = pos->y;
+ if (stroke_maxy < pos->y)
+ stroke_maxy = pos->y;
+ }
+}
+
+// test if strokefile exists; if not, create it from defaults.
+// if unable to create it,
+bool MTStroke::readSequence()
+{
+ QString strokefilename;
+ strokefilename = locate("config", "kmousetool_strokes.txt");
+ if (strokefilename.isEmpty()) {
+ // make default
+ if (sequenceMap.size()==0)
+ makeDefaultSequenceMap();
+ writeSequence();
+ return false;
+ }
+ ifstream infile (strokefilename.ascii());
+ if (!infile) {
+ // make default
+ if (sequenceMap.size()==0)
+ makeDefaultSequenceMap();
+ writeSequence();
+ return false;
+ }
+
+ while (!infile.eof()) {
+ string str;
+ infile >> str;
+ if (str[0] == '#')
+ readToEndOfLine(infile);
+ else {
+ // get the associated action
+ string str2;
+ infile >> str2;
+ int n = str2[0] - '0'; // the action is a single integer digit; convert it to an int
+ sequenceMap[ string(str) ] = n;
+ }
+ }
+ return true;
+}
+
+bool MTStroke::writeSequence()
+{
+ QString strokefilename;
+ strokefilename = locateLocal("config", "kmousetool_strokes.txt");
+
+ ofstream outfile (strokefilename.ascii(), ios::out);
+ if (!outfile) {
+ return false;
+ }
+
+ outfile << "# This file contains definitions for valid strokes for KMouseTool\n";
+ outfile << "# To make sense of the numbers: \n";
+ outfile << "# The mouse path begins and ends when the mouse is paused.\n";
+ outfile << "# Imagine a square enclosing the path.\n";
+ outfile << "# Divide the square into 9 boxes, and number them like so:\n";
+ outfile << "# 1 2 3\n";
+ outfile << "# 4 5 6\n";
+ outfile << "# 7 8 9\n";
+ outfile << "# \n";
+ outfile << "# The mouse path can then be described by a sequence of numbers:\n";
+ outfile << "# for example, \"12321\" describes the mouse moving from left to right and back.\n";
+ outfile << "# This general scheme follows libstroke (http://www.etla.net/~willey/projects/libstroke/)\n";
+ outfile << "# although it was reimplemented from scratch for KMouseTool.\n";
+ outfile << "\n";
+ outfile << "# For each stroke recognized, provide an integer describing an action\n";
+ outfile << "# KMouseTool can take. At the moment, valid actions are:\n";
+ outfile << "# -1 Don't click\n";
+ outfile << "# 1 Normal click (use Smart Drag if that's enabled)\n";
+ outfile << "# 2 Right click\n";
+ outfile << "# 3 Double click\n";
+ outfile << "\n";
+ outfile << "#Stroke\tAction\n";
+ std::map<std::string, int>::iterator pos = sequenceMap.begin();
+ while (pos != sequenceMap.end()) {
+ outfile << pos->first << "\t" << pos->second << "\n";
+ pos++;
+ }
+ return true;
+}
+
+void MTStroke::makeDefaultSequenceMap()
+{
+ sequenceMap[ string("12321") ] = RightClick;
+ sequenceMap[ string("1321") ] = RightClick;
+ sequenceMap[ string("1231") ] = RightClick;
+ sequenceMap[ string("131") ] = RightClick;
+
+ sequenceMap[ string("32123") ] = DoubleClick;
+ sequenceMap[ string("3213") ] = DoubleClick;
+ sequenceMap[ string("3123") ] = DoubleClick;
+ sequenceMap[ string("313") ] = DoubleClick;
+/*
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+*/
+}
+
+void MTStroke::readToEndOfLine(ifstream &infile)
+{
+ char ch = 'a';
+ while (ch != '\n')
+ infile.get(ch);
+}