presage  0.9.2~beta
presageDemo.cpp
Go to the documentation of this file.
1 
2 /******************************************************
3  * Presage, an extensible predictive text entry system
4  * ---------------------------------------------------
5  *
6  * Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  **********(*)*/
23 
24 
25 #include "presage.h"
26 
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 /* Solaris 10 needs to have NOMACROS defined to avoid conflict between
32  curses and standard template library code.
33  */
34 #ifndef NOMACROS
35 # define NOMACROS
36 # include <curses.h>
37 # undef NOMACROS
38 #else
39 # include <curses.h>
40 #endif
41 
42 #ifdef HAVE_STDLIB_H
43 # include <stdlib.h>
44 #endif
45 
46 #include <getopt.h>
47 
48 #include <iostream>
49 #include <sstream>
50 #include <list>
51 
52 const char PROGRAM_NAME[] = "presage_demo";
53 
54 // prototypes
55 //
56 void parseCommandLineArgs(int argc, char** argv);
57 void printUsage();
58 void printVersion();
59 
60 void disclaimer();
61 
62 void draw_title_win(WINDOW*);
63 void draw_context_win(WINDOW*, std::string);
64 void draw_function_keys(WINDOW*);
65 void draw_previous_suggestions(std::vector<std::string>, bool, const int, int);
66 size_t getGreatestSuggestionLength(std::vector< std::string > suggestions);
67 
68 // globals
69 std::string suggestions;
70 std::string config;
71 std::stringstream buffer; // text buffer, a real application would
72  // use something a little more
73  // sophisticated than a stringstream
74 
87 public:
88  PresageDemoCallback(std::stringstream& buffer) : m_buffer(buffer) { }
89 
90  std::string get_past_stream() const { return m_buffer.str(); }
91  std::string get_future_stream() const { return empty; }
92 
93 private:
94  std::stringstream& m_buffer;
95  const std::string empty;
96 
97 };
98 
114 int main(int argc, char** argv)
115 {
116  parseCommandLineArgs(argc, argv);
117 
118  // magic starts here
119  PresageCallback* callback = new PresageDemoCallback(buffer);
120  Presage presage(callback, config);
121 
122  // configuration variable may be read and written programmatically
123  if (suggestions.empty()) {
124  suggestions = presage.config("Presage.Selector.SUGGESTIONS");
125  } else {
126  presage.config("Presage.Selector.SUGGESTIONS", suggestions);
127  }
128 
129  // curses
130  initscr();
131  noecho();
132  cbreak();
133  keypad(stdscr, TRUE);
134  clear();
135  refresh();
136 
137  disclaimer();
138 
139  // curses title window
140  const int TITLE_WIN_HEIGHT = 6;
141  const int TITLE_WIN_WIDTH = COLS;
142  const int TITLE_WIN_BEGIN_Y = 0;
143  const int TITLE_WIN_BEGIN_X = 0;
144  WINDOW* title_win = newwin(TITLE_WIN_HEIGHT, TITLE_WIN_WIDTH, TITLE_WIN_BEGIN_Y, TITLE_WIN_BEGIN_X);
145  draw_title_win(title_win);
146 
147  // curses context window
148  const int CONTEXT_WIN_HEIGHT = 5;
149  const int CONTEXT_WIN_WIDTH = COLS;
150  const int CONTEXT_WIN_BEGIN_Y = TITLE_WIN_BEGIN_Y + TITLE_WIN_HEIGHT + 1;
151  const int CONTEXT_WIN_BEGIN_X = 0;
152  WINDOW* context_win = newwin(CONTEXT_WIN_HEIGHT, CONTEXT_WIN_WIDTH, CONTEXT_WIN_BEGIN_Y, CONTEXT_WIN_BEGIN_X);
153  draw_context_win(context_win, std::string(""));
154 
155  // curses function keys window
156  const int FUNCTION_WIN_HEIGHT = atoi(suggestions.c_str()) + 2;
157  const int FUNCTION_WIN_WIDTH = 4;
158  const int FUNCTION_WIN_BEGIN_Y = CONTEXT_WIN_BEGIN_Y + CONTEXT_WIN_HEIGHT + 1;
159  const int FUNCTION_WIN_BEGIN_X = 0;
160  WINDOW* function_win = newwin(FUNCTION_WIN_HEIGHT, FUNCTION_WIN_WIDTH, FUNCTION_WIN_BEGIN_Y, FUNCTION_WIN_BEGIN_X);
161  draw_function_keys(function_win);
162 
163  mvprintw(LINES - 1, 0, "Press F12 to quit.");
164  refresh();
165 
166 
167  std::vector<std::string> words;
168  unsigned int c = ' ';
169  do {
170  size_t size = words.size();
171  if ((KEY_F0 < c) && (c <= KEY_F(size)) && (c - KEY_F0 <= size)) {
172  // prediction was successful. user pressed the function
173  // key corresponding to desired token. selecting
174  // suggestion.
175  std::string message = "Last selected word: " + words[c - KEY_F0 - 1];
176  mvprintw(LINES - 3, 0, message.c_str());
177  clrtoeol();
178  move(LINES, COLS);
179 
180  // update buffer with prediction completion
181  buffer << presage.completion(words[c - KEY_F0 - 1]);
182  // ask presage to predict next token
183  words = presage.predict();
184 
185  } else {
186  // prediction unsuccessful. get next character from user
187  // and elaborate a new prediction.
188  buffer << static_cast<char>(c);
189  words = presage.predict();
190 
191  // refresh curses screen
192  refresh();
193  }
194  draw_context_win(context_win, presage.context());
196  presage.context_change(),
197  CONTEXT_WIN_BEGIN_Y + CONTEXT_WIN_HEIGHT + 1,
198  FUNCTION_WIN_BEGIN_X + FUNCTION_WIN_WIDTH + 1 );
199  c = getch();
200 
201  } while( c != KEY_F(12) );
202 
203  delwin(title_win);
204  delwin(context_win);
205  delwin(function_win);
206  endwin();
207 
208  return 0;
209 }
210 
211 
212 void draw_context_win(WINDOW* win, std::string str)
213 {
214  wclear( win );
215  box( win, 0, 0 );
216  mvwprintw( win, 1, 1, str.c_str() );
217  wrefresh( win );
218 }
219 
220 
221 void drawMsgWin( WINDOW* win, std::vector<std::string> words )
222 {
223  wclear( win );
224  box( win, 0, 0 );
225 
226  int i = 1;
227  std::vector<std::string>::const_iterator j = words.begin();
228  while( j != words.end() ) {
229  mvwprintw( win, i, 1, j->c_str() );
230  i++;
231  j++;
232  }
233 
234  wrefresh( win );
235 }
236 
237 void draw_function_keys(WINDOW* win)
238 {
239  wclear(win);
240  box(win, 0, 0);
241  for (int i = 1; i <= atoi(suggestions.c_str()); i++) {
242  std::stringstream ss;
243  ss << 'F' << i;
244  mvwprintw(win, i, 1, ss.str().c_str());
245  }
246  wrefresh(win);
247 }
248 
249 void draw_previous_suggestions(std::vector<std::string> words, bool contextChange,
250  const int starty, int startx)
251 {
252  static std::list< std::vector<std::string> > previousSuggestions;
253  static std::vector< WINDOW* > windows;
254 
255  // clear out existing windows
256  for (std::vector< WINDOW* >::iterator winit = windows.begin();
257  winit != windows.end();
258  winit++) {
259  wclear(*winit);
260  wrefresh(*winit);
261  delwin(*winit);
262  }
263  windows.clear();
264 
265  if (contextChange) {
266  // insert a context change marker in the list of previous
267  // suggestions
268  //
269  std::vector< std::string > marker;
270  for (int i = 0; i < atoi(suggestions.c_str()); i++) {
271  marker.push_back("|");
272  }
273  previousSuggestions.insert(previousSuggestions.begin(), marker);
274  }
275 
276  previousSuggestions.insert(previousSuggestions.begin(), words);
277 
278  for (std::list< std::vector<std::string> >::const_iterator listit = previousSuggestions.begin();
279  (listit != previousSuggestions.end() && startx < COLS); // don't draw window off the screen
280  listit++) {
281 
282  int height = listit->size() + 2;
283  int width = getGreatestSuggestionLength(*listit) + 2;
284 
285  WINDOW* win = newwin(height, width, starty, startx);
286  wclear(win);
287  box(win, 0, 0);
288 
289  int line = 1;
290  for (std::vector<std::string>::const_iterator strit = listit->begin();
291  strit != listit->end();
292  strit++) {
293 
294  mvwprintw(win, line, 1, strit->c_str());
295  line++;
296  }
297 
298  wrefresh(win);
299  windows.push_back(win);
300  startx += width + 2;
301  }
302 }
303 
304 size_t getGreatestSuggestionLength(std::vector< std::string > suggestions)
305 {
306  size_t result = 0;
307  for (std::vector< std::string >::const_iterator it = suggestions.begin();
308  it != suggestions.end();
309  it++) {
310  if (it->size() > result) {
311  result = it->size();
312  }
313  }
314  return result;
315 }
316 
318 {
319  int topBottomBorder = (LINES/8);
320  int borderWinHeight = 15;
321  int borderWinWidth = 70;
322  int sideBorder = (COLS - borderWinWidth) / 2;
323  WINDOW* borderWin = newwin(borderWinHeight, borderWinWidth, topBottomBorder, sideBorder);
324  WINDOW* disclaimerWin = newwin(borderWinHeight-2, borderWinWidth-2, topBottomBorder+1, sideBorder+1);
325  box(borderWin, 0, 0);
326  wrefresh(borderWin);
327  wprintw(disclaimerWin,
328  "Presage Demo\n"
329  "------------\n"
330  "This program is intended as a demonstration of Presage ONLY.\n"
331  "\n"
332  "The Presage project aims to provide an intelligent predictive\n"
333  "text entry platform.\n"
334  "\n"
335  "Its intent is NOT to provide a predictive text entry user interface.\n"
336  "Think of Presage as the predictive backend that sits behind a\n"
337  "shiny user interface and does all the predictive heavy lifting.\n"
338  );
339  mvwprintw(disclaimerWin, (borderWinHeight-2)-1, 1, "Press any key to continue...");
340  wrefresh(disclaimerWin);
341 
342  getch();
343 
344  delwin(disclaimerWin);
345  delwin(borderWin);
346 
347  clear();
348  refresh();
349 }
350 
351 void draw_title_win(WINDOW* title_win)
352 {
353  wclear(title_win);
354  box(title_win, 0, 0);
355  mvwprintw(title_win, 1, 1, "Presage Demo ", VERSION);
356  mvwprintw(title_win, 2, 1, "Copyright (C) Matteo Vescovi");
357  mvwprintw(title_win, 3, 1, "This is free software; see the source for copying conditions. There is NO");
358  mvwprintw(title_win, 4, 1, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
359  wrefresh(title_win);
360 }
361 
362 void parseCommandLineArgs(int argc, char* argv[])
363 {
364  int next_option;
365 
366  // getopt structures
367  const char* const short_options = "c:s:hv";
368 
369  const struct option long_options[] = {
370  { "config", required_argument, 0, 'c' },
371  { "suggestions", required_argument, 0, 's' },
372  { "help", no_argument, 0, 'h' },
373  { "version", no_argument, 0, 'v' },
374  { 0, 0, 0, 0 }
375  };
376 
377  do {
378  next_option = getopt_long( argc, argv,
379  short_options, long_options, NULL );
380 
381  switch( next_option ) {
382  case 'c': // --config or -c option
383  config = optarg;
384  break;
385  case 's': // --suggestions or -s option
386  suggestions = optarg;
387  break;
388  case 'h': // --help or -h option
389  printUsage();
390  exit (0);
391  break;
392  case 'v': // --version or -v option
393  printVersion();
394  exit (0);
395  break;
396  case '?': // unknown option
397  printUsage();
398  exit (0);
399  break;
400  case -1:
401  break;
402  default:
403  abort();
404  }
405 
406  } while( next_option != -1 );
407 }
408 
410 {
411  std::cout << PROGRAM_NAME << " (" << PACKAGE << ") version " << VERSION << std::endl
412  << "Copyright (C) 2004 Matteo Vescovi." << std::endl
413  << "This is free software; see the source for copying conditions. There is NO" << std::endl
414  << "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE," << std::endl
415  << "to the extent permitted by law." << std::endl;
416 }
417 
419 {
420  std::cout << "Usage: " << PROGRAM_NAME << " [OPTION]..." << std::endl
421  << std::endl
422  << "Begin typing. presage will attempt to predict the desired word." << std::endl
423  << "After each keystroke, presage will return a number of predictions." << std::endl
424  << "If the desired word appears in the prediction list, select it by pressing the" << std::endl
425  << "corresponding function key." << std::endl
426  << std::endl
427  << " -c, --config CONFIG use config file CONFIG" << std::endl
428  << " -s, --suggestions N set prediction size to N suggestions" << std::endl
429  << " -h, --help display this help and exit" << std::endl
430  << " -v, --version output version information and exit" << std::endl
431  << std::endl
432  << "Direct your bug reports to: " << PACKAGE_BUGREPORT << std::endl;
433 }
std::string config(const std::string variable) const
Gets the value of specified configuration variable.
Definition: presage.cpp:218
std::string get_past_stream() const
Definition: presageDemo.cpp:90
size_t getGreatestSuggestionLength(std::vector< std::string > suggestions)
std::vector< std::string > predict()
Obtain a prediction.
Definition: presage.cpp:64
const std::string empty
Definition: presageDemo.cpp:95
void draw_context_win(WINDOW *, std::string)
std::stringstream buffer
Definition: presageDemo.cpp:71
void draw_function_keys(WINDOW *)
PresageDemoCallback(std::stringstream &buffer)
Definition: presageDemo.cpp:88
void printVersion()
std::stringstream & m_buffer
Definition: presageDemo.cpp:94
void draw_title_win(WINDOW *)
std::string suggestions
Definition: presageDemo.cpp:69
void parseCommandLineArgs(int argc, char **argv)
void printUsage()
const char PROGRAM_NAME[]
Definition: presageDemo.cpp:52
std::string config
Definition: presageDemo.cpp:70
int main(int argc, char **argv)
void disclaimer()
bool context_change() const
Returns true if a context change occured.
Definition: presage.cpp:206
std::string get_future_stream() const
Definition: presageDemo.cpp:91
void draw_previous_suggestions(std::vector< std::string >, bool, const int, int)
Presage, the intelligent predictive text entry platform.
Definition: presage.h:107
void drawMsgWin(WINDOW *win, std::vector< std::string > words)
std::string context() const
Returns the text entered so far.
Definition: presage.cpp:200
std::string completion(std::string str)
Request presage to return the completion string for the given predicted token.
Definition: presage.cpp:152
const Logger< _charT, _Traits > & endl(const Logger< _charT, _Traits > &lgr)
Definition: logger.h:278