/*************************************************************************** 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 // these are for locating the stroke information file #include #include // #include 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::iterator pos; for (pos=points.begin(); posx && 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::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::iterator pos; for (pos=points.begin(); posx = (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::iterator pos; for (pos=points.begin(); pos 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() { TQString 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() { TQString 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::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); }