tkwidget.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /* Widgets for the Midnight Commander, Tk interface code
  2. Copyright (C) 1994, 1995, 1996 Miguel de Icaza
  3. Copyright (C) 1995 Jakub Jelinek
  4. Copyright (C) 1994 Radek Doulik
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. TODO: Destroy all the command names that are created for each
  17. widget during runtime.
  18. */
  19. #include <config.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <ctype.h>
  24. #include "tkmain.h"
  25. #include "tkwidget.h"
  26. #include "dlg.h"
  27. static char
  28. widget_number (Widget *w)
  29. {
  30. Dlg_head *h = w->parent;
  31. const int count = h->count;
  32. Widget_Item *item;
  33. int i;
  34. item = h->first;
  35. for (i = 0; i < count; i++){
  36. if (item->widget == w)
  37. return i;
  38. item = item->next;
  39. }
  40. /* Actually, if we get this far, this message should not appear */
  41. fprintf (stderr, "Inconsistent widget\n");
  42. exit (1);
  43. }
  44. /* Returns a new command prefixed with an x:
  45. x.query.$the_frame.b0
  46. for the command of the query dialog box button 0
  47. This allow us to control the widget with the command:
  48. .query.$the_frame.b0
  49. and to access the C code callback with the:
  50. x.query.$the_frame.b0
  51. command.
  52. */
  53. char *
  54. tk_new_command (widget_data parent, void *widget,
  55. tcl_callback callback, char id)
  56. {
  57. char buffer [60];
  58. Widget *w = (Widget *) widget;
  59. Dlg_head *h = w->parent;
  60. char *cmd;
  61. /* wdata holds the frame information, it will be replaced with the
  62. * the widget command name
  63. */
  64. if (h->grided && w->tkname)
  65. sprintf (buffer, ".widgets.%s", w->tkname);
  66. else {
  67. char *format;
  68. if (((char *) parent) [1] == 0)
  69. format = "%s%c%d";
  70. else
  71. format = ".%s%c%d";
  72. sprintf (buffer, format, w->frame, id, widget_number (w));
  73. }
  74. cmd = copy_strings ("x", (char *)parent, buffer, 0);
  75. w->wdata = (widget_data) cmd;
  76. if (callback)
  77. Tcl_CreateCommand (interp, cmd, callback, w, NULL);
  78. return cmd;
  79. }
  80. /* Button routines */
  81. static int
  82. is_default_button (WButton *b)
  83. {
  84. return b->action == B_ENTER;
  85. }
  86. /* Called from the Tcl/Tk program when a button has been pressed */
  87. static int
  88. tk_button_callback (ClientData cd, Tcl_Interp *interp, int argc, char *argv [])
  89. {
  90. WButton *b = (WButton *) cd;
  91. Dlg_head *h = (Dlg_head *) b->widget.parent;
  92. int stop = 0;
  93. char *cmd = wtcl_cmd (b->widget);
  94. if (b->callback)
  95. stop = (*b->callback)(b->action, b->callback_data);
  96. if (!b->callback || stop){
  97. h->running = 0;
  98. h->ret_value = b->action;
  99. }
  100. return TCL_OK;
  101. }
  102. void
  103. x_button_set (WButton *b, char *text)
  104. {
  105. char *cmd = wtcl_cmd (b->widget);
  106. char *postfix = is_default_button (b) ? ".button" : "";
  107. tk_evalf ("%s%s configure -text {%s}", cmd+1, postfix, text);
  108. }
  109. /* Creates the button $parent.$newname and executes $newname command */
  110. int
  111. x_create_button (Dlg_head *h, widget_data parent, WButton *b)
  112. {
  113. char *cmd;
  114. cmd = tk_new_command (parent, b, tk_button_callback, 'b');
  115. tk_evalf ("newbutton %s %s {%s} %d", cmd+1, cmd, b->text, is_default_button (b));
  116. return 1;
  117. }
  118. /* Radio button routines */
  119. static int
  120. tk_radio_callback (ClientData cd, Tcl_Interp *interp, int argc, char *argv [])
  121. {
  122. WRadio *r = (WRadio *) cd;
  123. if (STREQ (argv [1], "select")){
  124. r->pos = r->sel = atoi (argv [2]);
  125. }
  126. (r->widget.callback)(r->widget.parent, r, WIDGET_KEY, ' ');
  127. return TCL_OK;
  128. }
  129. void
  130. x_radio_focus_item (WRadio *r)
  131. {
  132. tk_evalf ("focus %s.%d", (char *)(r->widget.wdata)+1, r->pos);
  133. }
  134. int
  135. x_create_radio (Dlg_head *h, widget_data parent, WRadio *r)
  136. {
  137. int i;
  138. char *cmd;
  139. cmd = tk_new_command (parent, r, tk_radio_callback, 'r');
  140. tk_evalf ("newradio %s", cmd+1);
  141. for (i = 0; i < r->count; i++){
  142. tk_evalf ("radio_item %d {%s} %s %d", i, r->texts [i], cmd,
  143. r->sel == i);
  144. }
  145. return 1;
  146. }
  147. /* Checkbuttons routines */
  148. static int
  149. tk_check_callback (ClientData cd, Tcl_Interp *interp, int argc, char *argv [])
  150. {
  151. WCheck *c = (WCheck *) cd;
  152. Dlg_head *h = c->widget.parent;
  153. (*c->widget.callback)(h, c, WIDGET_KEY, ' ');
  154. return TCL_OK;
  155. }
  156. int
  157. x_create_check (Dlg_head *h, widget_data parent, WCheck *c)
  158. {
  159. char *cmd;
  160. cmd = tk_new_command (parent, c, tk_check_callback, 'c');
  161. tk_evalf ("newcheck %s %s {%s} %d", cmd+1, cmd, c->text, c->state);
  162. return 1;
  163. }
  164. /* Input line */
  165. int input_event (Gpm_Event *event, WInput *b);
  166. /* This callback command accepts the following commands:
  167. **
  168. ** $win mouse x-position
  169. ** $win setmark x-position
  170. */
  171. static int
  172. tk_input_callback (ClientData cd, Tcl_Interp *interp, int argc, char *av [])
  173. {
  174. Gpm_Event e;
  175. WInput *in = (WInput *) cd;
  176. if (strcmp (av [1], "mouse") == 0){
  177. e.x = atoi (av [2]) + 1;
  178. e.y = 0;
  179. e.type = GPM_DOWN;
  180. input_event (&e, (WInput *) cd);
  181. return TCL_OK;
  182. } else if (strcmp (av [1], "setmark") == 0){
  183. in->mark = in->point;
  184. return TCL_OK;
  185. }
  186. return TCL_OK;
  187. }
  188. void
  189. x_update_input (WInput *in)
  190. {
  191. char *name = wtcl_cmd (in->widget);
  192. int p;
  193. if (!name)
  194. return;
  195. name++;
  196. if (in->is_password){
  197. tk_evalf ("%s delete 0 end", name);
  198. tk_evalf ("%s insert end {*secret*}", name);
  199. p = 9;
  200. } else {
  201. tk_evalf ("entry_save_sel %s", name);
  202. if (in->inserted_one && isascii (in->inserted_one) && in->inserted_one > ' '){
  203. tk_evalf ("%s insert insert {%c}", name, in->inserted_one);
  204. in->inserted_one = 0;
  205. } else {
  206. tk_evalf ("%s delete 0 end", name);
  207. tk_evalf ("%s insert end {%s}", name, in->buffer);
  208. }
  209. p = in->point;
  210. }
  211. tk_evalf ("%s icursor %d; entry_restore_sel %s", name, p, name);
  212. }
  213. int
  214. x_create_input (Dlg_head *h, widget_data parent, WInput *in)
  215. {
  216. char *cmd;
  217. cmd = tk_new_command (parent, in, tk_input_callback, 'i');
  218. tk_evalf ("newinput %s {%s}", cmd+1, in->buffer ? in->buffer: "");
  219. return 1;
  220. }
  221. void
  222. x_listbox_select_nth (WListbox *l, int nth)
  223. {
  224. if (!wtcl_cmd (l->widget))
  225. return;
  226. tk_evalf ("listbox_sel %s %d", wtk_win (l->widget), nth);
  227. }
  228. void
  229. x_listbox_delete_nth (WListbox *l, int nth)
  230. {
  231. tk_evalf ("%s delete %d", wtk_win (l->widget), nth);
  232. }
  233. int
  234. x_create_listbox (Dlg_head *h, widget_data parent, WListbox *l)
  235. {
  236. char *cmd;
  237. int i;
  238. WLEntry *e;
  239. cmd = tk_new_command (parent, l, 0, 'x');
  240. tk_evalf ("listbox %s -width %d -selectmode single", cmd+1, l->widget.cols);
  241. /* As Jakub said on his very fine xvwidget.c: the user could add some
  242. * entries to the listbox before the tk-listbox was created, so we have
  243. * to add it manually :-)
  244. */
  245. i = 0;
  246. if ((e = l->list) == NULL)
  247. return 1;
  248. do {
  249. tk_evalf ("%s insert %d {%s}", cmd+1, i, e->text);
  250. if (e == l->current)
  251. x_listbox_select_nth (l, i);
  252. e = e->next;
  253. i++;
  254. } while (e != l->list);
  255. return 1;
  256. }
  257. /*
  258. * 30.10.96 bor: x_list_insert added in reverse order as x_create_listbox
  259. */
  260. void
  261. x_list_insert (WListbox *l, WLEntry *p, WLEntry *e)
  262. {
  263. int i;
  264. char *t = e->text;
  265. if (wtcl_cmd (l->widget) == NULL)
  266. return;
  267. for (i = 0; p != NULL && p != e; p = p->next, i++)
  268. ;
  269. tk_evalf ("%s insert %d {%s}", wtk_win (l->widget), i, t);
  270. }
  271. int
  272. x_create_label (Dlg_head *g, widget_data parent, WLabel *l)
  273. {
  274. char *cmd;
  275. cmd = tk_new_command (parent, l, 0, 'l');
  276. tk_evalf ("label %s -text {%s}", cmd+1, l->text);
  277. return 1;
  278. }
  279. void
  280. x_label_set_text (WLabel *label, char *text)
  281. {
  282. char *lname;
  283. if (!wtcl_cmd (label->widget))
  284. return;
  285. tk_evalf ("%s configure -text {%s}", wtk_win (label->widget),
  286. text ? text : "");
  287. }
  288. static int
  289. tk_buttonbar_callback (ClientData cd, Tcl_Interp *in, int ac, char *av [])
  290. {
  291. WButtonBar *bb = (WButtonBar *) cd;
  292. Dlg_head *h = (Dlg_head *) bb->widget.parent;
  293. int which = atoi (av [1]);
  294. (*bb->labels [which].function)(bb->labels [which].data);
  295. return TCL_OK;
  296. }
  297. int
  298. x_create_buttonbar (Dlg_head *h, widget_data parent, WButtonBar *bb)
  299. {
  300. char *cmd;
  301. int i;
  302. cmd = tk_new_command (parent, bb, tk_buttonbar_callback, 'n');
  303. tk_evalf ("frame %s", cmd+1);
  304. for (i = 0; i < 10; i++){
  305. tk_evalf ("newbutton %s.%d {%s %d} {%d %s} 0", cmd+1, i, cmd, i, i+1,
  306. bb->labels [i].text ? bb->labels [i].text : "");
  307. tk_evalf ("%s.%d configure -padx 1", cmd+1, i);
  308. tk_evalf ("pack %s.%d -side left -fill x -expand 1 -ipady 0",
  309. cmd+1, i);
  310. }
  311. return 1;
  312. }
  313. void
  314. x_redefine_label (WButtonBar *bb, int idx)
  315. {
  316. if (!bb->widget.wdata)
  317. return;
  318. if (!*(char *) bb->widget.wdata)
  319. return;
  320. if (!bb->labels [idx-1].text)
  321. return;
  322. tk_evalf ("%s.%d configure -text {%d %s}",
  323. wtk_win (bb->widget), idx-1, idx, bb->labels [idx-1].text);
  324. }
  325. /* destructor for the Tk widgets */
  326. void
  327. x_destroy_cmd (void *w)
  328. {
  329. Widget *widget = (Widget *)w;
  330. if (widget->wdata){
  331. Tcl_DeleteCommand (interp, wtcl_cmd (*widget));
  332. tk_evalf ("destroy %s", wtk_win (*widget));
  333. free (wtcl_cmd (*widget));
  334. }
  335. }
  336. int
  337. x_find_buttonbar_check (WButtonBar *bb, Widget *paneletc)
  338. {
  339. return (strcmp ((char *) bb->widget.wcontainer,
  340. (char *)paneletc->wcontainer));
  341. }
  342. /* The only parameter accepted is the size of the widget width */
  343. static int
  344. tk_gauge_callback (ClientData cd, Tcl_Interp *in, int ac, char *av [])
  345. {
  346. WGauge *g = (WGauge *) cd;
  347. g->pixels = atoi (av [1]);
  348. return TCL_OK;
  349. }
  350. int
  351. x_create_gauge (Dlg_head *h, widget_data parent, WGauge *g)
  352. {
  353. char *cmd;
  354. cmd = tk_new_command (parent, g, tk_gauge_callback, 'g');
  355. tk_evalf ("newgauge %s", cmd+1);
  356. return 1;
  357. }
  358. static void
  359. x_gauge_display (WGauge *g)
  360. {
  361. tk_evalf ("%s coords gauge 0 0 %d 90", wtk_win (g->widget),
  362. (int) (g->current*g->pixels)/g->max);
  363. }
  364. void
  365. x_gauge_show (WGauge *g)
  366. {
  367. tk_evalf ("gauge_%s %s", g->shown ? "shown":"hidden", wtk_win (g->widget));
  368. if (g->shown)
  369. x_gauge_display (g);
  370. }
  371. void
  372. x_gauge_set_value (WGauge *g, int max, int current)
  373. {
  374. if (g->shown)
  375. x_gauge_display (g);
  376. }