Scid  4.6.5
ui_tcltk.h
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2015 Fulvio Benini
3 
4 * This file is part of Scid (Shane's Chess Information Database).
5 *
6 * Scid is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation.
9 *
10 * Scid is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Scid. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifndef SCID_UI_TCLTK_H
20 #define SCID_UI_TCLTK_H
21 
22 #include "timer.h"
23 #include <tcl.h>
24 #include <sstream>
25 #include <limits>
26 
27 namespace UI_impl {
28 
29 
30 typedef int UI_res_t;
31 typedef ClientData UI_extra_t;
32 typedef Tcl_Interp* UI_handle_t;
33 
34 inline int initTclTk (UI_handle_t ti);
35 
36 inline int Main (int argc, char* argv[], void (*exit) (void*)) {
37  Tcl_FindExecutable(argv[0]);
38  Tcl_CreateExitHandler(exit, 0);
39  bool search_tcl = (argc == 1) ? true : false;
40  if (argc > 1 && argc < 10) {
41  char* ext = strrchr (argv[1], '.');
42  if (ext != 0 && strlen(ext) == 4 && std::string(".tcl") != ext) {
43  search_tcl = true;
44  }
45  }
46  if (search_tcl) {
47  char sourceFileName [4096] = {0};
48  #ifndef WIN32
49  // Expand symbolic links
50  char* exec_name = realpath(Tcl_GetNameOfExecutable(), 0);
51  strncpy(sourceFileName, exec_name, 4000);
52  free(exec_name);
53  #else
54  strncpy(sourceFileName, Tcl_GetNameOfExecutable(), 4000);
55  #endif
56 
57  char* dirname = strrchr(sourceFileName, '/');
58  if (dirname == 0) dirname = sourceFileName;
59  else dirname += 1;
60  strcpy (dirname, "tcl/start.tcl");
61  if (0 != Tcl_Access(sourceFileName, 4)) {
62  strcpy (dirname, "../tcl/start.tcl");
63  }
64  char* newArgv[10] = { argv[0], sourceFileName };
65  std::copy(argv + 1, argv + argc, newArgv + 2);
66  Tcl_Main(argc + 1, newArgv, UI_impl::initTclTk);
67  } else {
68  Tcl_Main (argc, argv, UI_impl::initTclTk);
69  }
70 
71  return 0;
72 }
73 
74 
75 class tcl_Progress : public Progress::Impl {
76  UI_handle_t ti_;
77  Timer timer_;
78 
79 public:
80  tcl_Progress(UI_handle_t ti) : ti_(ti) {}
81  virtual ~tcl_Progress() {}
82 
83  virtual bool report(size_t done, size_t total, const char* msg) {
84  ASSERT(done <= static_cast<size_t>(std::numeric_limits<int>::max()));
85  ASSERT(total <= static_cast<size_t>(std::numeric_limits<int>::max()));
86 
87  uint64_t elapsed = timer_.MilliSecs();
88  uint64_t estimated = (done == 0) ? 0 : elapsed * total / done;
89  Tcl_Obj* tmp[5];
90  tmp[0] = Tcl_NewStringObj("::progressCallBack", -1);
91  tmp[1] = Tcl_NewIntObj(static_cast<int>(done));
92  tmp[2] = Tcl_NewIntObj(static_cast<int>(total));
93  tmp[3] = Tcl_NewIntObj(static_cast<int>(elapsed / 1000));
94  tmp[4] = Tcl_NewIntObj(static_cast<int>(estimated / 1000));
95  Tcl_Obj* cmd = Tcl_NewListObj(5, tmp);
96  if (msg != NULL)
97  Tcl_ListObjAppendElement(ti_, cmd, Tcl_NewStringObj(msg, -1));
98  Tcl_IncrRefCount(cmd);
99  int res = Tcl_EvalObjEx(ti_, cmd, TCL_EVAL_GLOBAL);
100  Tcl_DecrRefCount(cmd);
101  return res == TCL_OK;
102  }
103 };
104 
106  UI_handle_t ti_;
107 
108 public:
109  tcl_ProgressPosMask(UI_handle_t ti) : ti_(ti) {}
110  virtual ~tcl_ProgressPosMask() {}
111 
112  virtual bool report(size_t, size_t, const char*) {
113  return TCL_OK == Tcl_EvalEx(ti_, "::windows::gamelist::PosMaskProgress", -1, 0);
114  }
115 };
116 
117 inline Progress CreateProgress(UI_handle_t data) {
118  int err = Tcl_EvalEx(data, "::progressCallBack init", -1, 0);
119  if (err != TCL_OK) return Progress();
120  return Progress(new UI_impl::tcl_Progress(data));
121 }
122 
123 inline Progress CreateProgressPosMask(UI_handle_t data) {
124  return Progress(new UI_impl::tcl_ProgressPosMask(data));
125 }
126 
127 
128 class List {
129  Tcl_Obj** list_;
130  mutable int i_;
131  Tcl_Obj* stackBuf_[6];
132 
133  friend Tcl_Obj* ObjMaker(const List&);
134 
135 public:
136  explicit List(size_t max_size)
137  : list_(stackBuf_), i_(0) {
138  const size_t stackBuf_size = sizeof(stackBuf_)/sizeof(stackBuf_[0]);
139  if (max_size > stackBuf_size) {
140  list_ = new Tcl_Obj*[max_size];
141  }
142  }
143 
144  ~List() {
145  clear();
146  if (list_ != stackBuf_) delete [] list_;
147  }
148 
149  void clear() {
150  for (int i=0; i < i_; i++) Tcl_DecrRefCount(list_[i]);
151  i_ = 0;
152  }
153 
154  void push_back(Tcl_Obj* value) {
155  ASSERT(value != 0);
156  list_[i_++] = value;
157  }
158  template <typename T>
159  void push_back(const T& value);
160 };
161 
162 inline Tcl_Obj* ObjMaker(bool v) {
163  return Tcl_NewBooleanObj(v);
164 }
165 inline Tcl_Obj* ObjMaker(int v) {
166  return Tcl_NewIntObj(v);
167 }
168 inline Tcl_Obj* ObjMaker(unsigned int v) {
169  ASSERT(v <= static_cast<unsigned int>(std::numeric_limits<int>::max()));
170  return Tcl_NewIntObj(static_cast<int>(v));
171 }
172 inline Tcl_Obj* ObjMaker(unsigned long v) {
173  ASSERT(v <= static_cast<unsigned long>(std::numeric_limits<int>::max()));
174  return Tcl_NewIntObj(static_cast<int>(v));
175 }
176 #if CPP11_SUPPORT
177 inline Tcl_Obj* ObjMaker(unsigned long long v) {
178  ASSERT(v <= static_cast<unsigned long long>(std::numeric_limits<int>::max()));
179  return Tcl_NewIntObj(static_cast<int>(v));
180 }
181 #endif
182 inline Tcl_Obj* ObjMaker(double v) {
183  return Tcl_NewDoubleObj(v);
184 }
185 inline Tcl_Obj* ObjMaker(const char* s) {
186  return Tcl_NewStringObj(s, -1);
187 }
188 inline Tcl_Obj* ObjMaker(const std::string& s) {
189  ASSERT(s.size() <= static_cast<size_t>(std::numeric_limits<int>::max()));
190  return Tcl_NewStringObj(s.c_str(), static_cast<int>(s.size()));
191 }
192 inline Tcl_Obj* ObjMaker(const List& v) {
193  Tcl_Obj* res = Tcl_NewListObj(v.i_, v.list_);
194  v.i_ = 0;
195  return res;
196 }
197 
198 template <typename T>
199 inline void List::push_back(const T& value) {
200  push_back(ObjMaker(value));
201 }
202 
203 
204 inline UI_res_t ResultHelper(UI_handle_t ti, errorT res) {
205  if (res == OK) return TCL_OK;
206  Tcl_SetObjErrorCode(ti, Tcl_NewIntObj(res));
207  return TCL_ERROR;
208 }
209 
210 inline UI_res_t Result(UI_handle_t ti, errorT res) {
211  Tcl_ResetResult(ti);
212  return UI_impl::ResultHelper(ti, res);
213 }
214 
215 template <typename T>
216 inline UI_res_t Result(UI_handle_t ti, errorT res, const T& value) {
217  Tcl_SetObjResult(ti, UI_impl::ObjMaker(value));
218  return UI_impl::ResultHelper(ti, res);
219 }
220 
221 } //End of UI_impl namespace
222 
223 
224 //TODO:
225 //Duplicate declarations (already in ui.h)
228 UI_impl::UI_res_t sc_base (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
229 UI_impl::UI_res_t sc_book (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
231 UI_impl::UI_res_t sc_eco (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
233 UI_impl::UI_res_t sc_game (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
234 UI_impl::UI_res_t sc_info (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
235 UI_impl::UI_res_t sc_move (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
236 UI_impl::UI_res_t sc_name (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
238 UI_impl::UI_res_t sc_pos (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
240 UI_impl::UI_res_t sc_tree (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
241 UI_impl::UI_res_t sc_var (UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char ** argv);
242 
243 inline int UI_impl::initTclTk (UI_handle_t ti)
244 {
245  if (Tcl_Init (ti) == TCL_ERROR) { return TCL_ERROR; }
246 
247  Tcl_CreateCommand(ti, "strIsPrefix" , str_is_prefix , 0, NULL);
248  Tcl_CreateCommand(ti, "strPrefixLen", str_prefix_len, 0, NULL);
249  Tcl_CreateCommand(ti, "sc_base" , sc_base , 0, NULL);
250  Tcl_CreateCommand(ti, "sc_book" , sc_book , 0, NULL);
251  Tcl_CreateCommand(ti, "sc_clipbase" , sc_clipbase , 0, NULL);
252  Tcl_CreateCommand(ti, "sc_eco" , sc_eco , 0, NULL);
253  Tcl_CreateCommand(ti, "sc_filter" , sc_filter , 0, NULL);
254  Tcl_CreateCommand(ti, "sc_game" , sc_game , 0, NULL);
255  Tcl_CreateCommand(ti, "sc_info" , sc_info , 0, NULL);
256  Tcl_CreateCommand(ti, "sc_move" , sc_move , 0, NULL);
257  Tcl_CreateCommand(ti, "sc_name" , sc_name , 0, NULL);
258  Tcl_CreateCommand(ti, "sc_report" , sc_report , 0, NULL);
259  Tcl_CreateCommand(ti, "sc_pos" , sc_pos , 0, NULL);
260  Tcl_CreateCommand(ti, "sc_search" , sc_search , 0, NULL);
261  Tcl_CreateCommand(ti, "sc_tree" , sc_tree , 0, NULL);
262  Tcl_CreateCommand(ti, "sc_var" , sc_var , 0, NULL);
263 
264  return TCL_OK;
265 }
266 
267 
268 #endif
Definition: timer.h:51
virtual bool report(size_t done, size_t total, const char *msg)
Definition: ui_tcltk.h:83
virtual ~tcl_Progress()
Definition: ui_tcltk.h:81
const errorT OK
Definition: error.h:23
uint max(int a, int b)
Definition: crosstab.cpp:237
#define ASSERT(f)
Definition: common.h:67
Definition: misc.h:124
UI_impl::UI_res_t sc_move(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:5385
UI_impl::UI_res_t str_is_prefix(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:293
Tcl_Obj * ObjMaker(bool v)
Definition: ui_tcltk.h:162
int UI_res_t
Definition: ui_tcltk.h:30
tcl_ProgressPosMask(UI_handle_t ti)
Definition: ui_tcltk.h:109
UI_res_t ResultHelper(UI_handle_t ti, errorT res)
Definition: ui_tcltk.h:204
UI_impl::UI_res_t sc_game(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
GAME functions.
Definition: tkscid.cpp:2146
int initTclTk(UI_handle_t ti)
Definition: ui_tcltk.h:243
UI_impl::UI_res_t sc_var(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:10178
virtual bool report(size_t, size_t, const char *)
Definition: ui_tcltk.h:112
int MilliSecs()
Definition: timer.h:60
UI_impl::UI_res_t sc_name(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:6455
UI_impl::UI_res_t sc_report(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:8134
UI_res_t Result(UI_handle_t ti, errorT res)
Definition: ui_tcltk.h:210
UI_impl::UI_res_t str_prefix_len(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:307
Progress CreateProgressPosMask(UI_handle_t data)
Definition: ui_tcltk.h:123
unsigned short errorT
Definition: error.h:20
void push_back(Tcl_Obj *value)
Definition: ui_tcltk.h:154
UI_impl::UI_res_t sc_clipbase(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:1200
clear?pattern?
We don&#39;t remove TooltipMenu because there.
int Main(int argc, char *argv[], void(*exit)(void *))
Definition: ui_tcltk.h:36
UI_impl::UI_res_t sc_tree(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:8488
tcl_Progress(UI_handle_t ti)
Definition: ui_tcltk.h:80
UI_impl::UI_res_t sc_search(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:9109
Tcl_Interp * UI_handle_t
Definition: ui_tcltk.h:32
cmd
Definition: fics.tcl:443
UI_impl::UI_res_t sc_eco(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:1280
List(size_t max_size)
Definition: ui_tcltk.h:136
Progress CreateProgress(UI_handle_t data)
Definition: ui_tcltk.h:117
UI_impl::UI_res_t sc_pos(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
Definition: tkscid.cpp:5642
UI_impl::UI_res_t sc_filter(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
UI_impl::UI_res_t sc_info(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
INFO functions.
Definition: tkscid.cpp:5049
void clear()
Definition: ui_tcltk.h:149
UI_impl::UI_res_t sc_book(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
BOOK functions.
Definition: tkscid.cpp:10351
UI_impl::UI_res_t sc_base(UI_impl::UI_extra_t, UI_impl::UI_handle_t, int argc, const char **argv)
ClientData UI_extra_t
Definition: ui_tcltk.h:31