canvs.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220
  1. #include <lib9.h>
  2. #include <kernel.h>
  3. #include "draw.h"
  4. #include "tk.h"
  5. #include "canvs.h"
  6. /* Widget Commands (+ means implemented)
  7. +addtag
  8. except halo and start options of closest spec
  9. +bbox
  10. +bind
  11. +canvasx
  12. +canvasy
  13. +cget
  14. +configure
  15. +coords
  16. +create
  17. +dchars
  18. +delete
  19. +dtag
  20. +find
  21. +focus
  22. +gettags
  23. +icursor
  24. +index
  25. +insert
  26. +itemcget
  27. +itemconfigure
  28. +lower
  29. +move
  30. postscript
  31. +raise
  32. +scale
  33. scan
  34. +select
  35. +type
  36. +xview
  37. +yview
  38. */
  39. static
  40. TkStab tkbuffer[] = {
  41. "visible", TkCbufvisible,
  42. "all", TkCbufall,
  43. "none", TkCbufnone,
  44. "auto", TkCbufauto,
  45. /* backwards compatibility */
  46. "1", TkCbufall,
  47. "yes", TkCbufall,
  48. "off", TkCbufall,
  49. "0", TkCbufauto,
  50. "no", TkCbufauto,
  51. "off", TkCbufauto,
  52. nil
  53. };
  54. #define O(t, e) ((long)(&((t*)0)->e))
  55. #define OA(t, e) ((long)(((t*)0)->e))
  56. static
  57. TkOption opts[] =
  58. {
  59. "closeenough", OPTfrac, O(TkCanvas, close), nil,
  60. "confine", OPTfrac, O(TkCanvas, confine), nil,
  61. "scrollregion", OPTfrac, OA(TkCanvas, scrollr), IAUX(4),
  62. "xscrollincrement", OPTfrac, O(TkCanvas, xscrolli), nil,
  63. "yscrollincrement", OPTfrac, O(TkCanvas, yscrolli), nil,
  64. "xscrollcommand", OPTtext, O(TkCanvas, xscroll), nil,
  65. "yscrollcommand", OPTtext, O(TkCanvas, yscroll), nil,
  66. "width", OPTnnfrac, O(TkCanvas, width), nil,
  67. "height", OPTnnfrac, O(TkCanvas, height), nil,
  68. "buffer", OPTstab, O(TkCanvas, buffer), tkbuffer,
  69. "buffered", OPTstab, O(TkCanvas, buffer), tkbool, /* backwards compatibility */
  70. "selectborderwidth", OPTnndist, O(TkCanvas, sborderwidth), nil,
  71. nil
  72. };
  73. int cvslshape[] = { TKI2F(8), TKI2F(10), TKI2F(3) };
  74. Rectangle bbnil = { 1000000, 1000000, -1000000, -1000000 };
  75. Rectangle huger = { -1000000, -1000000, 1000000, 1000000 };
  76. static void tkcvsgeom(Tk *tk);
  77. static void
  78. tkcvsf2i(Tk *tk, TkCanvas *tkc)
  79. {
  80. Rectangle r;
  81. tk->req.width = TKF2I(tkc->width);
  82. tk->req.height = TKF2I(tkc->height);
  83. r.min.x = TKF2I(tkc->scrollr[0]);
  84. r.min.y = TKF2I(tkc->scrollr[1]);
  85. r.max.x = TKF2I(tkc->scrollr[2]);
  86. r.max.y = TKF2I(tkc->scrollr[3]);
  87. /*
  88. * make sure that the region is big enough to hold
  89. * the actually displayed area
  90. */
  91. if (Dx(r) < tk->act.width)
  92. r.max.x = r.min.x + tk->act.width;
  93. if (Dy(r) < tk->act.height)
  94. r.max.y = r.min.y + tk->act.height;
  95. tkc->region = r;
  96. /*
  97. * make sure that the view origin is at a valid
  98. * position with respect to the scroll region.
  99. */
  100. if (tkc->view.x + tk->act.width > r.max.x)
  101. tkc->view.x = r.max.x - tk->act.width;
  102. if (tkc->view.x < r.min.x)
  103. tkc->view.x = r.min.x;
  104. if (tkc->view.y + tk->act.height > r.max.y)
  105. tkc->view.y = r.max.y - tk->act.height;
  106. if (tkc->view.y < r.min.y)
  107. tkc->view.y = r.min.y;
  108. }
  109. char*
  110. tkcanvas(TkTop *t, char *arg, char **ret)
  111. {
  112. Tk *tk;
  113. char *e;
  114. TkCanvas *tkc;
  115. TkName *names;
  116. TkOptab tko[3];
  117. tk = tknewobj(t, TKcanvas, sizeof(Tk)+sizeof(TkCanvas));
  118. if(tk == nil)
  119. return TkNomem;
  120. tkc = TKobj(TkCanvas, tk);
  121. tkc->close = TKI2F(1);
  122. tkc->xscrolli = TKI2F(1);
  123. tkc->yscrolli = TKI2F(1);
  124. tkc->width = TKI2F(360);
  125. tkc->height = TKI2F(270);
  126. tkc->actions = 0;
  127. tkc->actlim = Tksweep;
  128. tkc->mask = nil;
  129. tkc->sborderwidth = 1;
  130. tko[0].ptr = tkc;
  131. tko[0].optab = opts;
  132. tko[1].ptr = tk;
  133. tko[1].optab = tkgeneric;
  134. tko[2].ptr = nil;
  135. names = nil;
  136. e = tkparse(t, arg, tko, &names);
  137. if(e != nil)
  138. goto err;
  139. if(names == nil) {
  140. /* tkerr(t, arg); XXX */
  141. e = TkBadwp;
  142. goto err;
  143. }
  144. tkc->current = tkmkname("current");
  145. if(tkc->current == nil) {
  146. e = TkNomem;
  147. goto err;
  148. }
  149. tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
  150. tkcvsf2i(tk, tkc);
  151. e = tkaddchild(t, tk, &names);
  152. tkfreename(names);
  153. if(e != nil) {
  154. tkfreename(tkc->current);
  155. tkc->current = nil;
  156. goto err;
  157. }
  158. tk->name->link = nil;
  159. e = tkvalue(ret, "%s", tk->name->name);
  160. if(e == nil)
  161. return nil;
  162. tkfreename(tkc->current);
  163. return e;
  164. err:
  165. tkfreeobj(tk);
  166. return e;
  167. }
  168. void
  169. tkcvsdirty(Tk *sub)
  170. {
  171. TkCanvas *c;
  172. Tk *tk, *parent;
  173. Rectangle r;
  174. Point rel;
  175. rel = ZP;
  176. for(tk = sub; tk; tk = tk->master) {
  177. rel.x += tk->borderwidth + tk->act.x;
  178. rel.y += tk->borderwidth + tk->act.y;
  179. if (tk->parent != nil)
  180. break;
  181. }
  182. if (tk == nil)
  183. return;
  184. parent = tk->parent;
  185. c = TKobj(TkCanvas, parent);
  186. r = rectaddpt(sub->dirty, rel);
  187. tkbbmax(&c->update, &r);
  188. tkcvssetdirty(parent);
  189. }
  190. static void
  191. tkcvsfocusorder(Tk *tk)
  192. {
  193. TkCanvas *tkc = TKobj(TkCanvas, tk);
  194. TkCwind *win;
  195. TkCitem *it;
  196. TkWinfo *inf;
  197. int i, n;
  198. n = 0;
  199. for (it = tkc->head; it != nil; it = it->next) {
  200. if (it->type == TkCVwindow) {
  201. win = TKobj(TkCwind, it);
  202. if (win->sub != nil)
  203. n++;
  204. }
  205. }
  206. if (n == 0)
  207. return;
  208. inf = malloc(sizeof(*inf) * n);
  209. if (inf == nil)
  210. return;
  211. i = 0;
  212. for (it = tkc->head; it != nil; it = it->next) {
  213. if (it->type == TkCVwindow) {
  214. win = TKobj(TkCwind, it);
  215. if (win->sub != nil) {
  216. inf[i].w = win->sub;
  217. inf[i].r = it->p.bb;
  218. i++;
  219. }
  220. }
  221. }
  222. tksortfocusorder(inf, n);
  223. for (i = 0; i < n; i++)
  224. tkappendfocusorder(inf[i].w);
  225. }
  226. static char*
  227. tkcvscget(Tk *tk, char *arg, char **val)
  228. {
  229. TkOptab tko[3];
  230. TkCanvas *tkc = TKobj(TkCanvas, tk);
  231. tko[0].ptr = tkc;
  232. tko[0].optab = opts;
  233. tko[1].ptr = tk;
  234. tko[1].optab = tkgeneric;
  235. tko[2].ptr = nil;
  236. return tkgencget(tko, arg, val, tk->env->top);
  237. }
  238. static char*
  239. tkcvsconf(Tk *tk, char *arg, char **val)
  240. {
  241. char *e;
  242. int bd;
  243. TkGeom g;
  244. Rectangle r;
  245. TkOptab tko[3];
  246. TkCanvas *c = TKobj(TkCanvas, tk);
  247. tko[0].ptr = c;
  248. tko[0].optab = opts;
  249. tko[1].ptr = tk;
  250. tko[1].optab = tkgeneric;
  251. tko[2].ptr = nil;
  252. if(*arg == '\0')
  253. return tkconflist(tko, val);
  254. r.min = c->view;
  255. r.max.x = r.min.x+tk->act.width;
  256. r.max.y = r.min.y+tk->act.height;
  257. tkbbmax(&c->update, &r);
  258. tkbbmax(&c->update, &c->region);
  259. bd = tk->borderwidth;
  260. g = tk->req;
  261. e = tkparse(tk->env->top, arg, tko, nil);
  262. if(e != nil)
  263. return e;
  264. tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
  265. tkcvsf2i(tk, c);
  266. tkcvsgeom(tk);
  267. tkgeomchg(tk, &g, bd);
  268. tkbbmax(&c->update, &c->region);
  269. tk->dirty = tkrect(tk, 1);
  270. return nil;
  271. }
  272. void
  273. tkcvsfreeitem(TkCitem *i)
  274. {
  275. int locked;
  276. Display *d;
  277. d = i->env->top->display;
  278. locked = lockdisplay(d);
  279. tkcimethod[i->type].free(i);
  280. if(locked)
  281. unlockdisplay(d);
  282. tkfreepoint(&i->p);
  283. tkputenv(i->env);
  284. free(i);
  285. }
  286. void
  287. tkfreecanv(Tk *tk)
  288. {
  289. Display *d;
  290. int j, locked;
  291. TkCanvas *c;
  292. TkName *n, *nn;
  293. TkCtag *t, *tt;
  294. TkCitem *i, *next;
  295. c = TKobj(TkCanvas, tk);
  296. for(i = c->head; i; i = next) {
  297. next = i->next;
  298. tkcvsfreeitem(i);
  299. }
  300. if(c->xscroll != nil)
  301. free(c->xscroll);
  302. if(c->yscroll != nil)
  303. free(c->yscroll);
  304. for(j = 0; j < TkChash; j++) {
  305. for(n = c->thash[j]; n; n = nn) {
  306. nn = n->link;
  307. for(t = n->obj; t; t = tt) {
  308. tt = t->taglist;
  309. free(t);
  310. }
  311. tkfreebind(n->prop.binds);
  312. free(n);
  313. }
  314. }
  315. free(c->current);
  316. if((c->ialloc && c->image != nil) || c->mask != nil) {
  317. if (c->ialloc && c->image != nil)
  318. d = c->image->display;
  319. else
  320. d = c->mask->display;
  321. locked = lockdisplay(d);
  322. if (c->image != nil && c->ialloc)
  323. freeimage(c->image);
  324. if (c->mask != nil)
  325. freeimage(c->mask);
  326. if(locked)
  327. unlockdisplay(d);
  328. }
  329. }
  330. char*
  331. tkdrawcanv(Tk *tk, Point orig)
  332. {
  333. Image *dst;
  334. TkCitem *i;
  335. Display *d;
  336. TkCanvas *c;
  337. Rectangle r, bufr, oclipr;
  338. int vis, alpha, buffer;
  339. Point rel, p;
  340. TkCimeth *imeth;
  341. c = TKobj(TkCanvas, tk);
  342. d = tk->env->top->display;
  343. dst = tkimageof(tk);
  344. /*
  345. * translation from local to screen coords
  346. */
  347. rel.x = orig.x + tk->act.x + tk->borderwidth;
  348. rel.y = orig.y + tk->act.y + tk->borderwidth;
  349. buffer = c->buffer;
  350. if (buffer == TkCbufauto)
  351. buffer = TkCbufvisible;
  352. /* buffer = (dst == TKobj(TkWin, tk->env->top->root)->image) ? TkCbufvisible : TkCbufnone; */
  353. if (buffer == TkCbufnone) {
  354. if(c->image != nil && c->ialloc)
  355. freeimage(c->image);
  356. c->image = dst;
  357. c->ialloc = 0;
  358. r = tkrect(tk, 0);
  359. bufr = r;
  360. rectclip(&bufr, tk->dirty);
  361. oclipr = dst->clipr;
  362. replclipr(dst, 0, rectaddpt(bufr, rel));
  363. draw(dst, rectaddpt(bufr, rel), tkgc(tk->env, TkCbackgnd), nil, ZP);
  364. p = subpt(rel, c->view);
  365. p.x = TKI2F(p.x);
  366. p.y = TKI2F(p.y);
  367. bufr = rectaddpt(bufr, c->view);
  368. for(i = c->head; i; i = i->next) {
  369. if(rectXrect(i->p.bb, bufr)) {
  370. imeth = &tkcimethod[i->type];
  371. imeth->coord(i, nil, p.x, p.y);
  372. imeth->draw(dst, i, tk->env);
  373. imeth->coord(i, nil, -p.x, -p.y);
  374. }
  375. }
  376. replclipr(dst, 0, oclipr);
  377. } else {
  378. if (c->buffer == TkCbufall)
  379. bufr = c->region;
  380. else {
  381. bufr.min = c->view;
  382. bufr.max.x = c->view.x + tk->act.width;
  383. bufr.max.y = c->view.y + tk->act.height;
  384. }
  385. alpha = (tk->env->colors[TkCbackgnd] & 0xff) != 0xff;
  386. if(c->image == nil || eqrect(bufr, c->image->r) == 0) {
  387. if(c->image != nil && c->ialloc)
  388. freeimage(c->image);
  389. c->image = allocimage(d, bufr, alpha?RGBA32:d->image->chan, 0, tk->env->colors[TkCbackgnd]);
  390. c->ialloc = 1;
  391. c->update = bufr;
  392. tkcvssetdirty(tk); /* unnecessary? */
  393. }
  394. if(c->image == nil)
  395. return nil;
  396. r = c->update;
  397. if (rectclip(&r, c->image->r)) {
  398. if (alpha)
  399. drawop(c->image, c->update, nil, nil, ZP, Clear);
  400. draw(c->image, c->update, tkgc(tk->env, TkCbackgnd), nil, c->view);
  401. replclipr(c->image, 0, r);
  402. for(i = c->head; i; i = i->next) {
  403. if(rectXrect(i->p.bb, r))
  404. tkcimethod[i->type].draw(c->image, i, tk->env);
  405. }
  406. replclipr(c->image, 0, c->image->r);
  407. }
  408. /*
  409. * if the visible area of the canvas image doesn't
  410. * fit completely within the dirty rectangle,
  411. * then we'll need to draw the background behind it
  412. */
  413. r = tkrect(tk, 0);
  414. bufr = rectsubpt(bufr, c->view);
  415. vis = rectclip(&bufr, tkrect(tk, 0));
  416. if (!vis || !rectinrect(tk->dirty, bufr))
  417. draw(dst, rectaddpt(tk->dirty, rel), tkgc(tk->env, TkCbackgnd), nil, c->view);
  418. if (vis && rectclip(&bufr, tk->dirty))
  419. draw(dst, rectaddpt(bufr, rel), c->image, nil, addpt(bufr.min, c->view));
  420. }
  421. /*
  422. * if the border is dirty too, then draw that
  423. */
  424. if (!rectinrect(tk->dirty, bufr)) {
  425. r.min = addpt(r.min, rel);
  426. r.min.x -= tk->borderwidth;
  427. r.min.y -= tk->borderwidth;
  428. tkdrawrelief(dst, tk, r.min, TkCbackgnd, tk->relief);
  429. }
  430. c->update = bbnil;
  431. return nil;
  432. }
  433. void
  434. tkcvsappend(TkCanvas *c, TkCitem *i)
  435. {
  436. if(c->head == nil)
  437. c->head = i;
  438. else
  439. c->tail->next = i;
  440. c->tail = i;
  441. }
  442. void
  443. tkcvssv(Tk *tk)
  444. {
  445. TkCanvas *c;
  446. int top, bot, height;
  447. char val[Tkminitem], cmd[Tkmaxitem], *v, *e;
  448. c = TKobj(TkCanvas, tk);
  449. if(c->yscroll == nil)
  450. return;
  451. top = 0;
  452. bot = TKI2F(1);
  453. height = Dy(c->region);
  454. if(height != 0) {
  455. top = TKI2F(c->view.y)/height;
  456. bot = TKI2F(c->view.y+tk->act.height)/height;
  457. }
  458. v = tkfprint(val, top);
  459. *v++ = ' ';
  460. tkfprint(v, bot);
  461. snprint(cmd, sizeof(cmd), "%s %s", c->yscroll, val);
  462. e = tkexec(tk->env->top, cmd, nil);
  463. if ((e != nil) && (tk->name != nil))
  464. print("tk: yscrollcommand \"%s\": %s\n", tk->name->name, e);
  465. }
  466. void
  467. tkcvssh(Tk *tk)
  468. {
  469. int top, bot, width;
  470. TkCanvas *c = TKobj(TkCanvas, tk);
  471. char val[Tkminitem], cmd[Tkmaxitem], *v, *e;
  472. if(c->xscroll == nil)
  473. return;
  474. top = 0;
  475. bot = TKI2F(1);
  476. width = Dx(c->region);
  477. if(width != 0) {
  478. top = TKI2F(c->view.x)/width;
  479. bot = TKI2F(c->view.x+tk->act.width)/width;
  480. }
  481. v = tkfprint(val, top);
  482. *v++ = ' ';
  483. tkfprint(v, bot);
  484. snprint(cmd, sizeof(cmd), "%s %s", c->xscroll, val);
  485. e = tkexec(tk->env->top, cmd, nil);
  486. if ((e != nil) && (tk->name != nil))
  487. print("tk: xscrollcommand \"%s\": %s\n", tk->name->name, e);
  488. }
  489. static void
  490. tkcvsgeom(Tk *tk)
  491. {
  492. TkCanvas *c;
  493. c = TKobj(TkCanvas, tk);
  494. tkcvsf2i(tk, c);
  495. tk->dirty = tkrect(tk, 1);
  496. c->update = c->region;
  497. tkcvssv(tk);
  498. tkcvssh(tk);
  499. }
  500. char*
  501. tkcvstags(Tk *tk, char *arg, char **val, int af)
  502. {
  503. TkTop *o;
  504. int x, y;
  505. TkName *f;
  506. TkCtag *t, *tt;
  507. char *fmt;
  508. TkCpoints p;
  509. TkCanvas *c;
  510. TkCitem *i, *b;
  511. int d, dist, dx, dy;
  512. char tag[Tkmaxitem], buf[Tkmaxitem];
  513. char *e;
  514. USED(val);
  515. c = TKobj(TkCanvas, tk);
  516. o = tk->env->top;
  517. if(af == TkCadd) {
  518. arg = tkword(o, arg, tag, tag+sizeof(tag), nil);
  519. if(tag[0] == '\0' || (tag[0] >= '0' && tag[0] <= '9'))
  520. return TkBadtg;
  521. }
  522. fmt = "%d";
  523. arg = tkword(o, arg, buf, buf+sizeof(buf), nil);
  524. if(strcmp(buf, "above") == 0) {
  525. tkword(o, arg, buf, buf+sizeof(buf), nil);
  526. f = tkctaglook(tk, nil, buf);
  527. if(f == nil)
  528. return TkBadtg;
  529. t = tkclasttag(c->head, f->obj);
  530. if(t == nil)
  531. return TkBadtg;
  532. for(i = t->item->next; i; i = i->next) {
  533. if(af == TkCadd) {
  534. i->tags = tkmkname(tag);
  535. if(i->tags == nil)
  536. return TkNomem;
  537. tkcaddtag(tk, i, 0);
  538. }
  539. else {
  540. e = tkvalue(val, fmt, i->id);
  541. if(e != nil)
  542. return e;
  543. fmt = " %d";
  544. }
  545. }
  546. return nil;
  547. }
  548. if(strcmp(buf, "all") == 0) {
  549. for(i = c->head; i; i = i->next) {
  550. if(af == TkCadd) {
  551. i->tags = tkmkname(tag);
  552. if(i->tags == nil)
  553. return TkNomem;
  554. tkcaddtag(tk, i, 0);
  555. }
  556. else {
  557. e = tkvalue(val, fmt, i->id);
  558. if(e != nil)
  559. return e;
  560. fmt = " %d";
  561. }
  562. }
  563. return nil;
  564. }
  565. if(strcmp(buf, "below") == 0) {
  566. tkword(o, arg, buf, buf+sizeof(buf), nil);
  567. f = tkctaglook(tk, nil, buf);
  568. if(f == nil)
  569. return TkBadtg;
  570. tt = f->obj;
  571. for(b = c->head; b; b = b->next) {
  572. for(t = tt; t; t = t->itemlist)
  573. if(t->item == b)
  574. goto found;
  575. }
  576. found:
  577. for(i = c->head; i != b; i = i->next) {
  578. if(af == TkCadd) {
  579. i->tags = tkmkname(tag);
  580. if(i->tags == nil)
  581. return TkNomem;
  582. tkcaddtag(tk, i, 0);
  583. }
  584. else {
  585. e = tkvalue(val, fmt, i->id);
  586. if(e != nil)
  587. return e;
  588. fmt = " %d";
  589. }
  590. }
  591. return nil;
  592. }
  593. if(strcmp(buf, "closest") == 0) {
  594. e = tkfracword(o, &arg, &x, nil);
  595. if (e == nil)
  596. e = tkfracword(o, &arg, &y, nil);
  597. if (e != nil)
  598. return e;
  599. if(*arg != '\0')
  600. return "!not implemented";
  601. x = TKF2I(x);
  602. y = TKF2I(y);
  603. i = nil;
  604. dist = 0;
  605. for(b = c->head; b != nil; b = b->next) {
  606. dx = x - (b->p.bb.min.x + Dx(b->p.bb)/2);
  607. dy = y - (b->p.bb.min.y + Dy(b->p.bb)/2);
  608. d = dx*dx + dy*dy;
  609. if(d < dist || dist == 0) {
  610. i = b;
  611. dist = d;
  612. }
  613. }
  614. if(i == nil)
  615. return nil;
  616. if(af == TkCadd) {
  617. i->tags = tkmkname(tag);
  618. if(i->tags == nil)
  619. e = TkNomem;
  620. else
  621. tkcaddtag(tk, i, 0);
  622. }
  623. else
  624. e = tkvalue(val, fmt, i->id);
  625. return e;
  626. }
  627. if(strcmp(buf, "withtag") == 0) {
  628. tkword(o, arg, buf, buf+sizeof(buf), nil);
  629. f = tkctaglook(tk, nil, buf);
  630. if(f == nil)
  631. return TkBadtg;
  632. for(t = f->obj; t; t = t->taglist) {
  633. i = t->item;
  634. if(af == TkCadd) {
  635. i->tags = tkmkname(tag);
  636. if(i->tags == nil)
  637. return TkNomem;
  638. tkcaddtag(tk, i, 0);
  639. }
  640. else {
  641. e = tkvalue(val, fmt, i->id);
  642. if(e != nil)
  643. return e;
  644. fmt = " %d";
  645. }
  646. }
  647. return nil;
  648. }
  649. if(strcmp(buf, "enclosed") == 0) {
  650. e = tkparsepts(o, &p, &arg, 0);
  651. if(e != nil)
  652. goto done;
  653. if(p.npoint != 2) {
  654. e = TkFewpt;
  655. goto done;
  656. }
  657. for(i = c->head; i; i = i->next) {
  658. if(rectinrect(i->p.bb, p.bb)) {
  659. if(af == TkCadd) {
  660. i->tags = tkmkname(tag);
  661. if(i->tags == nil) {
  662. e = TkNomem;
  663. goto done;
  664. }
  665. tkcaddtag(tk, i, 0);
  666. }
  667. else {
  668. e = tkvalue(val, fmt, i->id);
  669. if(e != nil)
  670. goto done;
  671. fmt = " %d";
  672. }
  673. }
  674. }
  675. goto done;
  676. }
  677. if(strcmp(buf, "overlapping") == 0) {
  678. e = tkparsepts(o, &p, &arg, 0);
  679. if(e != nil)
  680. goto done;
  681. if(p.npoint != 2) {
  682. e = TkFewpt;
  683. goto done;
  684. }
  685. for(i = c->head; i; i = i->next) {
  686. if(rectXrect(i->p.bb, p.bb)) {
  687. if(af == TkCadd) {
  688. i->tags = tkmkname(tag);
  689. if(i->tags == nil) {
  690. e = TkNomem;
  691. goto done;
  692. }
  693. tkcaddtag(tk, i, 0);
  694. }
  695. else {
  696. e = tkvalue(val, "%d ", i->id);
  697. if(e != nil)
  698. goto done;
  699. }
  700. }
  701. }
  702. goto done;
  703. }
  704. return TkBadcm;
  705. done: /* both no error and error do the same thing */
  706. tkfreepoint(&p);
  707. return e;
  708. }
  709. static char*
  710. tkcvsaddtag(Tk *tk, char *arg, char **val)
  711. {
  712. return tkcvstags(tk, arg, val, TkCadd);
  713. }
  714. static char*
  715. tkcvsfind(Tk *tk, char *arg, char **val)
  716. {
  717. return tkcvstags(tk, arg, val, TkCfind);
  718. }
  719. static void
  720. tksweepcanv(Tk *tk)
  721. {
  722. int j, k;
  723. TkCtag *t, *tt;
  724. TkName **np, *n, *nn;
  725. TkCitem *i;
  726. TkCanvas *c;
  727. TkAction *a;
  728. c = TKobj(TkCanvas, tk);
  729. for(j = 0; j < TkChash; j++)
  730. for(n = c->thash[j]; n != nil; n = n->link)
  731. n->ref = 0;
  732. for(i = c->head; i != nil; i = i->next)
  733. for(t = i->stag; t != nil; t = t->itemlist)
  734. t->name->ref = 1;
  735. k = 0;
  736. for(j = 0; j < TkChash; j++) {
  737. np = &c->thash[j];
  738. for(n = *np; n != nil; n = nn) {
  739. nn = n->link;
  740. if(n->ref == 0) {
  741. for(t = n->obj; t != nil; t = tt) {
  742. tt = t->taglist;
  743. free(t);
  744. }
  745. tkfreebind(n->prop.binds);
  746. free(n);
  747. *np = nn;
  748. } else {
  749. np = &n->link;
  750. for(a = n->prop.binds; a != nil; a = a->link)
  751. k++;
  752. }
  753. }
  754. }
  755. c->actions = k;
  756. k = 3 * k / 2;
  757. if (k < Tksweep)
  758. c->actlim = Tksweep;
  759. else
  760. c->actlim = k;
  761. }
  762. /*
  763. * extension to tcl/tk:
  764. * grab set tag
  765. * grab release tag
  766. * grab ifunset tag
  767. */
  768. static char*
  769. tkcvsgrab(Tk *tk, char *arg, char **val)
  770. {
  771. TkCtag *t;
  772. TkName *f;
  773. TkCanvas *c;
  774. char buf[Tkmaxitem];
  775. c = TKobj(TkCanvas, tk);
  776. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  777. if (strcmp(buf, "status") == 0) {
  778. if (c->grab != nil)
  779. return tkvalue(val, "%d", c->grab->id);
  780. }
  781. else if (strcmp(buf, "release") == 0) {
  782. c->grab = nil;
  783. }
  784. else if (strcmp(buf, "set") == 0 || strcmp(buf, "ifunset") == 0) {
  785. if (buf[0] == 'i' && c->grab != nil)
  786. return nil;
  787. tkword(tk->env->top, arg, buf, buf + sizeof(buf), nil);
  788. f = tkctaglook(tk, nil, buf);
  789. if(f == nil || f->obj == nil)
  790. return TkBadtg;
  791. c = TKobj(TkCanvas, tk);
  792. t = tkcfirsttag(c->head, f->obj);
  793. if(t == nil)
  794. return TkBadtg;
  795. c->grab = t->item;
  796. }
  797. else
  798. return TkBadvl;
  799. return nil;
  800. }
  801. static char*
  802. tkcvsbind(Tk *tk, char *arg, char **val)
  803. {
  804. Rune r;
  805. TkCtag *t;
  806. TkName *f;
  807. TkAction *a;
  808. TkCanvas *c;
  809. int event, mode;
  810. char *cmd, buf[Tkmaxitem];
  811. char *e;
  812. c = TKobj(TkCanvas, tk);
  813. if (c->actions >= c->actlim)
  814. tksweepcanv(tk);
  815. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  816. f = tkctaglook(tk, nil, buf);
  817. if(f == nil) {
  818. f = tkctaglook(tk, tkmkname(buf), buf);
  819. if(f == nil)
  820. return TkNomem;
  821. }
  822. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  823. if(buf[0] == '<') {
  824. event = tkseqparse(buf+1);
  825. if(event == -1)
  826. return TkBadsq;
  827. }
  828. else {
  829. chartorune(&r, buf);
  830. event = TkKey | r;
  831. }
  832. if(event == 0)
  833. return TkBadsq;
  834. arg = tkskip(arg, " \t");
  835. if(*arg == '\0') {
  836. for(t = f->obj; t; t = t->taglist) {
  837. for(a = t->name->prop.binds; a; a = a->link)
  838. if(event == a->event)
  839. return tkvalue(val, "%s", a->arg);
  840. for(a = t->name->prop.binds; a; a = a->link)
  841. if(event & a->event)
  842. return tkvalue(val, "%s", a->arg);
  843. }
  844. return nil;
  845. }
  846. mode = TkArepl;
  847. if(*arg == '+') {
  848. mode = TkAadd;
  849. arg++;
  850. }
  851. else if(*arg == '-'){
  852. mode = TkAsub;
  853. arg++;
  854. }
  855. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  856. cmd = strdup(buf);
  857. if(cmd == nil)
  858. return TkNomem;
  859. e = tkaction(&f->prop.binds, event, TkDynamic, cmd, mode);
  860. if(e == nil)
  861. c->actions++;
  862. return e;
  863. }
  864. static char*
  865. tkcvscreate(Tk *tk, char *arg, char **val)
  866. {
  867. TkCimeth *m;
  868. char buf[Tkmaxitem];
  869. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  870. for(m = tkcimethod; m->name; m++)
  871. if(strcmp(buf, m->name) == 0)
  872. return m->create(tk, arg, val);
  873. return TkBadit;
  874. }
  875. static char*
  876. tkcvsbbox(Tk *tk, char *arg, char **val)
  877. {
  878. TkName *f;
  879. TkCtag *t;
  880. Rectangle bb;
  881. char buf[Tkmaxitem];
  882. bb = bbnil;
  883. for(;;) {
  884. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  885. if(buf[0] == '\0')
  886. break;
  887. f = tkctaglook(tk, nil, buf);
  888. if(f == nil)
  889. return TkBadtg;
  890. for(t = f->obj; t; t = t->taglist)
  891. tkbbmax(&bb, &t->item->p.bb);
  892. }
  893. return tkvalue(val, "%d %d %d %d", bb.min.x, bb.min.y, bb.max.x, bb.max.y);
  894. }
  895. static char*
  896. tkcvscanvx(Tk *tk, char *arg, char **val)
  897. {
  898. int x, s;
  899. TkCanvas *c;
  900. Point p;
  901. char buf[Tkmaxitem];
  902. c = TKobj(TkCanvas, tk);
  903. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  904. if(buf[0] == '\0')
  905. return TkBadvl;
  906. p = tkposn(tk);
  907. x = atoi(buf) + c->view.x - (p.x + tk->borderwidth);
  908. if(*arg) {
  909. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  910. s = atoi(buf);
  911. if (s) {
  912. if (x>=0)
  913. x = ((x+s/2)/s)*s;
  914. else
  915. x = ((x-s/2)/s)*s;
  916. }
  917. }
  918. return tkvalue(val, "%d", x);
  919. }
  920. static char*
  921. tkcvscanvy(Tk *tk, char *arg, char **val)
  922. {
  923. int y, s;
  924. TkCanvas *c;
  925. Point p;
  926. char buf[Tkmaxitem];
  927. c = TKobj(TkCanvas, tk);
  928. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  929. if(buf[0] == '\0')
  930. return TkBadvl;
  931. p = tkposn(tk);
  932. y = atoi(buf) + c->view.y - (p.y + tk->borderwidth);
  933. if(*arg) {
  934. tkitem(buf, arg);
  935. s = atoi(buf);
  936. if (s) {
  937. if (y>=0)
  938. y = ((y+s/2)/s)*s;
  939. else
  940. y = ((y-s/2)/s)*s;
  941. }
  942. }
  943. return tkvalue(val, "%d", y);
  944. }
  945. static char *
  946. tkcvsscreenx(Tk *tk, char *arg, char **val)
  947. {
  948. int x;
  949. TkCanvas *c;
  950. Point p;
  951. char buf[Tkmaxitem];
  952. c = TKobj(TkCanvas, tk);
  953. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  954. if(buf[0] == '\0')
  955. return TkBadvl;
  956. p = tkposn(tk);
  957. x = atoi(buf) - c->view.x + (p.x + tk->borderwidth);
  958. return tkvalue(val, "%d", x);
  959. }
  960. static char *
  961. tkcvsscreeny(Tk *tk, char *arg, char **val)
  962. {
  963. int y;
  964. TkCanvas *c;
  965. Point p;
  966. char buf[Tkmaxitem];
  967. c = TKobj(TkCanvas, tk);
  968. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  969. if(buf[0] == '\0')
  970. return TkBadvl;
  971. p = tkposn(tk);
  972. y = atoi(buf) - c->view.y + (p.y + tk->borderwidth);
  973. return tkvalue(val, "%d", y);
  974. }
  975. static char*
  976. tkcvscoords(Tk *tk, char *arg, char **val)
  977. {
  978. int i;
  979. Point *p;
  980. TkCtag *t;
  981. TkName *f;
  982. TkCanvas *c;
  983. TkCitem *item;
  984. char *fmt, *e, *v, buf[Tkmaxitem];
  985. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  986. if(buf[0] == '\0')
  987. return TkBadvl;
  988. f = tkctaglook(tk, nil, buf);
  989. if(f == nil || f->obj == nil)
  990. return TkBadtg;
  991. c = TKobj(TkCanvas, tk);
  992. t = tkcfirsttag(c->head, f->obj);
  993. if(t == nil)
  994. return TkBadtg;
  995. item = t->item;
  996. if(*arg == '\0') {
  997. fmt = "%s";
  998. p = item->p.parampt;
  999. for(i = 0; i < item->p.npoint; i++) {
  1000. v = tkfprint(buf, p->x);
  1001. *v++ = ' ';
  1002. tkfprint(v, p->y);
  1003. e = tkvalue(val, fmt, buf);
  1004. if(e != nil)
  1005. return e;
  1006. fmt = " %s";
  1007. p++;
  1008. }
  1009. return nil;
  1010. }
  1011. tkbbmax(&c->update, &item->p.bb);
  1012. e = tkcimethod[item->type].coord(item, arg, 0, 0);
  1013. tkbbmax(&c->update, &item->p.bb);
  1014. tkcvssetdirty(tk);
  1015. return e;
  1016. }
  1017. static char*
  1018. tkcvsscale(Tk *tk, char *arg, char **val)
  1019. {
  1020. TkName *f;
  1021. TkCtag *t;
  1022. TkCanvas *c;
  1023. TkCpoints pts;
  1024. TkCitem *item;
  1025. int j;
  1026. char *e, buf[Tkmaxitem];
  1027. Point *p, *d, origin, scalef;
  1028. USED(val);
  1029. c = TKobj(TkCanvas, tk);
  1030. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1031. f = tkctaglook(tk, nil, buf);
  1032. if(f == nil || f->obj == nil)
  1033. return TkBadtg;
  1034. e = tkparsepts(tk->env->top, &pts, &arg, 0);
  1035. if(e != nil)
  1036. return e;
  1037. if(pts.npoint != 2) {
  1038. tkfreepoint(&pts);
  1039. return TkFewpt;
  1040. }
  1041. origin = pts.parampt[0];
  1042. scalef = pts.parampt[1];
  1043. tkfreepoint(&pts);
  1044. for(t = f->obj; t; t = t->taglist) {
  1045. item = t->item;
  1046. p = item->p.parampt;
  1047. d = item->p.drawpt;
  1048. for(j = 0; j < item->p.npoint; j++) {
  1049. p->x -= origin.x;
  1050. p->y -= origin.y;
  1051. p->x = TKF2I(p->x*scalef.x);
  1052. p->y = TKF2I(p->y*scalef.y);
  1053. p->x += origin.x;
  1054. p->y += origin.y;
  1055. d->x = TKF2I(p->x);
  1056. d->y = TKF2I(p->y);
  1057. d++;
  1058. p++;
  1059. }
  1060. tkbbmax(&c->update, &item->p.bb);
  1061. e = tkcimethod[item->type].coord(item, nil, 0, 0);
  1062. tkbbmax(&c->update, &item->p.bb);
  1063. if(e != nil)
  1064. return e;
  1065. tkcvssetdirty(tk);
  1066. }
  1067. return nil;
  1068. }
  1069. static char*
  1070. tkcvsdtag(Tk *tk, char *arg, char **val)
  1071. {
  1072. TkName *f, *dt;
  1073. char buf[Tkmaxitem];
  1074. TkCtag **l, *t, *it, *tf;
  1075. USED(val);
  1076. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1077. f = tkctaglook(tk, nil, buf);
  1078. if(f == nil || f->obj == nil)
  1079. return TkBadtg;
  1080. /*
  1081. XXX this code doesn't appear to work properly.
  1082. fix it later. for the moment, it's just a somewhat more
  1083. efficient substitute for the later code, so just use that
  1084. instead.
  1085. if(*arg == '\0') {
  1086. for(t = f->obj; t; t = tf) {
  1087. l = &t->item->stag;
  1088. for(it = *l; it; it = it->itemlist) {
  1089. if(it->item == t->item) {
  1090. *l = it->itemlist;
  1091. break;
  1092. }
  1093. l = &it->itemlist;
  1094. }
  1095. tf = t->taglist;
  1096. free(t);
  1097. }
  1098. f->obj = nil;
  1099. return nil;
  1100. }
  1101. */
  1102. if (*arg == '\0')
  1103. dt = f;
  1104. else {
  1105. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1106. dt = tkctaglook(tk, nil, buf);
  1107. if(dt == nil || dt->obj == nil)
  1108. return TkBadtg;
  1109. }
  1110. for(t = f->obj; t; t = t->taglist) {
  1111. l = (TkCtag **)&dt->obj;
  1112. for(it = dt->obj; it; it = it->taglist) {
  1113. if(t->item == it->item) {
  1114. *l = it->taglist;
  1115. l = &t->item->stag;
  1116. for(tf = *l; tf; tf = tf->itemlist) {
  1117. if(tf == it) {
  1118. *l = tf->itemlist;
  1119. break;
  1120. }
  1121. l = &tf->itemlist;
  1122. }
  1123. free(it);
  1124. break;
  1125. }
  1126. l = &it->taglist;
  1127. }
  1128. }
  1129. return nil;
  1130. }
  1131. static char*
  1132. tkcvsdchars(Tk *tk, char *arg, char **val)
  1133. {
  1134. TkCtag *t;
  1135. TkName *f;
  1136. char *e, buf[Tkmaxitem];
  1137. USED(val);
  1138. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1139. f = tkctaglook(tk, nil, buf);
  1140. if(f == nil || f->obj == nil)
  1141. return TkBadtg;
  1142. for(t = f->obj; t; t = t->taglist) {
  1143. if(t->item->type == TkCVtext) {
  1144. e = tkcvstextdchar(tk, t->item, arg);
  1145. if(e != nil)
  1146. return e;
  1147. }
  1148. }
  1149. return nil;
  1150. }
  1151. static char*
  1152. tkcvsindex(Tk *tk, char *arg, char **val)
  1153. {
  1154. TkCtag *t;
  1155. TkName *f;
  1156. char *e, buf[Tkmaxitem];
  1157. USED(val);
  1158. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1159. f = tkctaglook(tk, nil, buf);
  1160. if(f == nil || f->obj == nil)
  1161. return TkBadtg;
  1162. for(t = f->obj; t; t = t->taglist) {
  1163. if(t->item->type == TkCVtext) {
  1164. e = tkcvstextindex(tk, t->item, arg, val);
  1165. if(e != nil)
  1166. return e;
  1167. return nil;
  1168. }
  1169. }
  1170. return nil;
  1171. }
  1172. static char*
  1173. tkcvsicursor(Tk *tk, char *arg, char **val)
  1174. {
  1175. TkCtag *t;
  1176. TkName *f;
  1177. char *e, buf[Tkmaxitem];
  1178. USED(val);
  1179. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1180. f = tkctaglook(tk, nil, buf);
  1181. if(f == nil || f->obj == nil)
  1182. return TkBadtg;
  1183. for(t = f->obj; t; t = t->taglist) {
  1184. if(t->item->type == TkCVtext) {
  1185. e = tkcvstexticursor(tk, t->item, arg);
  1186. if(e != nil)
  1187. return e;
  1188. return nil;
  1189. }
  1190. }
  1191. return nil;
  1192. }
  1193. static char*
  1194. tkcvsinsert(Tk *tk, char *arg, char **val)
  1195. {
  1196. TkCtag *t;
  1197. TkName *f;
  1198. char *e, buf[Tkmaxitem];
  1199. USED(val);
  1200. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1201. f = tkctaglook(tk, nil, buf);
  1202. if(f == nil || f->obj == nil)
  1203. return TkBadtg;
  1204. for(t = f->obj; t; t = t->taglist) {
  1205. if(t->item->type == TkCVtext) {
  1206. e = tkcvstextinsert(tk, t->item, arg);
  1207. if(e != nil)
  1208. return e;
  1209. }
  1210. }
  1211. return nil;
  1212. }
  1213. static char*
  1214. tkcvsselect(Tk *tk, char *arg, char **val)
  1215. {
  1216. int op;
  1217. TkCtag *t;
  1218. TkName *f;
  1219. TkCanvas *c;
  1220. char buf[Tkmaxitem];
  1221. c = TKobj(TkCanvas, tk);
  1222. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1223. if(strcmp(buf, "clear") == 0) {
  1224. tkcvstextclr(tk);
  1225. return nil;
  1226. }
  1227. if(strcmp(buf, "item") == 0) {
  1228. if(c->selection)
  1229. return tkvalue(val, "%d", c->selection->id);
  1230. return nil;
  1231. }
  1232. if(strcmp(buf, "to") == 0)
  1233. op = TkCselto;
  1234. else
  1235. if(strcmp(buf, "from") == 0)
  1236. op = TkCselfrom;
  1237. else
  1238. if(strcmp(buf, "adjust") == 0)
  1239. op = TkCseladjust;
  1240. else
  1241. return TkBadcm;
  1242. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1243. f = tkctaglook(tk, nil, buf);
  1244. if(f == nil)
  1245. return TkBadtg;
  1246. t = tkcfirsttag(c->head, f->obj);
  1247. if(t == nil)
  1248. return TkBadtg;
  1249. return tkcvstextselect(tk, t->item, arg, op);
  1250. }
  1251. static char*
  1252. tkcvsitemcget(Tk *tk, char *arg, char **val)
  1253. {
  1254. TkName *f;
  1255. TkCtag *t;
  1256. TkCitem *i;
  1257. char buf[Tkmaxitem];
  1258. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1259. f = tkctaglook(tk, nil, buf);
  1260. if(f == nil || f->obj == nil)
  1261. return TkBadtg;
  1262. for(i = TKobj(TkCanvas, tk)->head; i; i = i->next) {
  1263. for(t = f->obj; t; t = t->taglist)
  1264. if(i == t->item)
  1265. return tkcimethod[i->type].cget(i, arg, val);
  1266. }
  1267. return nil;
  1268. }
  1269. static char*
  1270. tkcvsitemconf(Tk *tk, char *arg, char **val)
  1271. {
  1272. char *e;
  1273. TkName *f;
  1274. TkCtag *t;
  1275. TkCitem *i;
  1276. TkCanvas *c;
  1277. char buf[Tkmaxitem];
  1278. USED(val);
  1279. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1280. f = tkctaglook(tk, nil, buf);
  1281. if(f == nil || f->obj == nil)
  1282. return TkBadtg;
  1283. c = TKobj(TkCanvas, tk);
  1284. for(t = f->obj; t; t = t->taglist) {
  1285. for(i = c->head; i; i = i->next) {
  1286. if(i == t->item) {
  1287. tkbbmax(&c->update, &i->p.bb);
  1288. e = tkcimethod[i->type].conf(tk, i, arg);
  1289. tkbbmax(&c->update, &i->p.bb);
  1290. tkcvssetdirty(tk);
  1291. if(e != nil)
  1292. return e;
  1293. }
  1294. }
  1295. }
  1296. return nil;
  1297. }
  1298. static void
  1299. tkcvsfreename(TkCanvas *c, TkName *n)
  1300. {
  1301. ulong h;
  1302. char *p, *s;
  1303. TkName *f, **l;
  1304. /* just free implicit ones for now */
  1305. if(n == nil)
  1306. return;
  1307. s = n->name;
  1308. if(s == nil || (s[0] < '0' || s[0] > '9'))
  1309. return;
  1310. h = 0;
  1311. for(p = s; *p; p++)
  1312. h += 3*h + *p;
  1313. l = &c->thash[h%TkChash];
  1314. for(f = *l; f; l = &f->link, f = *l)
  1315. if(f == n){
  1316. *l = f->link;
  1317. tkfreebind(f->prop.binds);
  1318. free(f);
  1319. return;
  1320. }
  1321. }
  1322. static char*
  1323. tkcvsdelete(Tk *tk, char *arg, char **val)
  1324. {
  1325. TkName *f;
  1326. TkCanvas *c;
  1327. char buf[Tkmaxitem];
  1328. TkCitem *item, *prev, *i;
  1329. TkCtag *t, *inext, **l, *dit, *it;
  1330. USED(val);
  1331. c = TKobj(TkCanvas, tk);
  1332. for(;;) {
  1333. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1334. if(buf[0] == '\0')
  1335. break;
  1336. f = tkctaglook(tk, nil, buf);
  1337. if(f == nil || f->obj == nil)
  1338. return nil;
  1339. while(f->obj) {
  1340. t = f->obj;
  1341. item = t->item;
  1342. for(it = item->stag; it; it = inext) {
  1343. inext = it->itemlist;
  1344. l = (TkCtag **)&it->name->obj;
  1345. for(dit = *l; dit; dit = dit->taglist) {
  1346. if(dit->item == item) {
  1347. *l = dit->taglist;
  1348. if(dit != t){
  1349. tkcvsfreename(c, dit->name);
  1350. free(dit);
  1351. }
  1352. break;
  1353. }
  1354. l = &dit->taglist;
  1355. }
  1356. }
  1357. tkbbmax(&c->update, &item->p.bb);
  1358. tkcvssetdirty(tk);
  1359. prev = nil;
  1360. for(i = c->head; i; i = i->next) {
  1361. if(i == item)
  1362. break;
  1363. prev = i;
  1364. }
  1365. if(prev == nil)
  1366. c->head = i->next;
  1367. else
  1368. prev->next = i->next;
  1369. if(c->tail == item)
  1370. c->tail = prev;
  1371. if(c->focus == item)
  1372. c->focus = nil;
  1373. if(c->mouse == item)
  1374. c->mouse = nil;
  1375. if(c->selection == item)
  1376. c->selection = nil;
  1377. if(c->curtag.item == item)
  1378. c->current->obj = nil;
  1379. if (c->grab == item)
  1380. c->grab = nil;
  1381. tkcvsfreeitem(item);
  1382. free(t);
  1383. }
  1384. }
  1385. return nil;
  1386. }
  1387. static char*
  1388. tkcvsfocus(Tk *tk, char *arg, char **val)
  1389. {
  1390. TkName *f;
  1391. TkCtag *t;
  1392. TkCanvas *c;
  1393. TkCitem *i, *focus;
  1394. char buf[Tkmaxitem];
  1395. c = TKobj(TkCanvas, tk);
  1396. if(*arg == '\0') {
  1397. if(c->focus == nil)
  1398. return nil;
  1399. return tkvalue(val, "%d", c->focus->id);
  1400. }
  1401. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1402. if(buf[0] == '\0')
  1403. return TkBadvl;
  1404. f = tkctaglook(tk, nil, buf);
  1405. if(f == nil || f->obj == nil)
  1406. return nil;
  1407. focus = c->focus;
  1408. if(focus != nil && focus->type == TkCVtext)
  1409. tkcvstextfocus(tk, focus, 0);
  1410. for(i = c->head; i; i = i->next) {
  1411. if(i->type == TkCVtext || i->type == TkCVwindow) {
  1412. for(t = f->obj; t; t = t->taglist)
  1413. if(t->item == i)
  1414. focus = i;
  1415. }
  1416. }
  1417. if(focus != nil && focus->type == TkCVtext)
  1418. tkcvstextfocus(tk, focus, 1);
  1419. c->focus = focus;
  1420. return nil;
  1421. }
  1422. static char*
  1423. tkcvsgettags(Tk *tk, char *arg, char **val)
  1424. {
  1425. TkCtag *t;
  1426. TkName *f;
  1427. TkCanvas *c;
  1428. char *fmt, *e, buf[Tkmaxitem];
  1429. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1430. if(buf[0] == '\0')
  1431. return TkBadvl;
  1432. f = tkctaglook(tk, nil, buf);
  1433. if(f == nil)
  1434. return TkBadtg;
  1435. c = TKobj(TkCanvas, tk);
  1436. t = tkclasttag(c->head, f->obj);
  1437. if(t == nil)
  1438. return TkBadtg;
  1439. fmt = "%s";
  1440. t = t->item->stag;
  1441. while(t) {
  1442. /* XXX when might t->name be legally nil? */
  1443. if (t->name != nil) {
  1444. if (strcmp(t->name->name, "all")) {
  1445. e = tkvalue(val, fmt, t->name->name);
  1446. if(e != nil)
  1447. return e;
  1448. fmt = " %s";
  1449. }
  1450. }
  1451. t = t->itemlist;
  1452. }
  1453. return nil;
  1454. }
  1455. static char*
  1456. tkcvslower(Tk *tk, char *arg, char **val)
  1457. {
  1458. TkCtag *t;
  1459. TkCanvas *c;
  1460. TkName *f, *b;
  1461. char buf[Tkmaxitem];
  1462. TkCitem *it, **l, **below, *items, **itemtail, *prev, *iprev;
  1463. USED(val);
  1464. c = TKobj(TkCanvas, tk);
  1465. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1466. f = tkctaglook(tk, nil, buf);
  1467. if(f == nil || f->obj == nil)
  1468. return nil;
  1469. below = &c->head;
  1470. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1471. if(buf[0] != '\0') {
  1472. b = tkctaglook(tk, nil, buf);
  1473. if(b == nil || f->obj == nil)
  1474. return TkBadtg;
  1475. for(it = c->head; it; it = it->next) {
  1476. for(t = b->obj; t; t = t->taglist)
  1477. if(t->item == it)
  1478. goto found;
  1479. below = &it->next;
  1480. }
  1481. found:;
  1482. }
  1483. l = &c->head;
  1484. prev = iprev = nil;
  1485. itemtail = &items;;
  1486. for (it = *l; it != nil; it = *l) {
  1487. for (t = f->obj; t; t = t->taglist) {
  1488. if(t->item == it) {
  1489. if (it == *below || below == &it->next)
  1490. below = l;
  1491. if (it == c->tail)
  1492. c->tail = prev;
  1493. *l = it->next;
  1494. *itemtail = it;
  1495. iprev = it;
  1496. itemtail = &it->next;
  1497. tkbbmax(&c->update, &it->p.bb);
  1498. goto next;
  1499. }
  1500. }
  1501. prev = it;
  1502. l = &it->next;
  1503. next:;
  1504. }
  1505. if (prev == nil)
  1506. c->tail = iprev;
  1507. *itemtail = *below;
  1508. *below = items;
  1509. tkcvssetdirty(tk);
  1510. return nil;
  1511. }
  1512. static char*
  1513. tkcvsmove(Tk *tk, char *arg, char **val)
  1514. {
  1515. TkCtag *t;
  1516. int fx, fy;
  1517. TkTop *top;
  1518. TkCpoints *p;
  1519. TkName *tag;
  1520. Rectangle *u;
  1521. TkCitem *item;
  1522. char *e;
  1523. char buf[Tkmaxitem];
  1524. USED(val);
  1525. top = tk->env->top;
  1526. arg = tkword(top, arg, buf, buf+sizeof(buf), nil);
  1527. tag = tkctaglook(tk, nil, buf);
  1528. if(tag == nil)
  1529. return nil;
  1530. e = tkfracword(top, &arg, &fx, nil);
  1531. if (e != nil)
  1532. return e;
  1533. e = tkfracword(top, &arg, &fy, nil);
  1534. if(e != nil)
  1535. return e;
  1536. u = &TKobj(TkCanvas, tk)->update;
  1537. for(t = tag->obj; t; t = t->taglist) {
  1538. item = t->item;
  1539. p = &item->p;
  1540. tkbbmax(u, &p->bb);
  1541. tkcimethod[item->type].coord(item, nil, fx, fy);
  1542. tkbbmax(u, &p->bb);
  1543. }
  1544. tkcvssetdirty(tk);
  1545. return nil;
  1546. }
  1547. static char*
  1548. tkcvsraise(Tk *tk, char *arg, char **val)
  1549. {
  1550. TkCtag *t;
  1551. TkCanvas *c;
  1552. TkName *f, *a;
  1553. char buf[Tkmaxitem];
  1554. TkCitem *prev, *it, *above, *items, *itemtail, *next;
  1555. USED(val);
  1556. c = TKobj(TkCanvas, tk);
  1557. arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1558. f = tkctaglook(tk, nil, buf);
  1559. if(f == nil)
  1560. return nil;
  1561. above = c->tail;
  1562. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1563. if(buf[0] != '\0') {
  1564. a = tkctaglook(tk, nil, buf);
  1565. if(a == nil)
  1566. return TkBadtg;
  1567. /*
  1568. * find topmost item in the display list matching the "above" tag
  1569. */
  1570. for(it = c->head; it != nil; it = it->next) {
  1571. for(t = a->obj; t; t = t->taglist)
  1572. if(t->item == it)
  1573. above = it;
  1574. }
  1575. }
  1576. prev = nil;
  1577. items = itemtail = nil;
  1578. for (it = c->head; it != nil; it = next) {
  1579. next = it->next;
  1580. for (t = f->obj; t; t = t->taglist) {
  1581. if(t->item == it) {
  1582. if (it == above)
  1583. above = next;
  1584. if (prev)
  1585. prev->next = next;
  1586. else
  1587. c->head = next;
  1588. if (itemtail)
  1589. itemtail->next = it;
  1590. else
  1591. items = it;
  1592. itemtail = it;
  1593. tkbbmax(&c->update, &it->p.bb);
  1594. goto next;
  1595. }
  1596. }
  1597. prev = it;
  1598. next:;
  1599. }
  1600. if (items != nil) {
  1601. if (above) {
  1602. itemtail->next = above->next;
  1603. if (above->next == nil)
  1604. c->tail = itemtail;
  1605. above->next = items;
  1606. } else {
  1607. if (prev)
  1608. prev->next = items;
  1609. else
  1610. c->head = items;
  1611. c->tail = itemtail;
  1612. itemtail->next = nil;
  1613. }
  1614. }
  1615. tkcvssetdirty(tk);
  1616. return nil;
  1617. }
  1618. static char*
  1619. tkcvstype(Tk *tk, char *arg, char **val)
  1620. {
  1621. TkCtag *t;
  1622. TkName *f;
  1623. TkCanvas *c;
  1624. char buf[Tkmaxitem];
  1625. tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
  1626. if(buf[0] == '\0')
  1627. return TkBadvl;
  1628. f = tkctaglook(tk, nil, buf);
  1629. if(f == nil || f->obj == nil)
  1630. return nil;
  1631. c = TKobj(TkCanvas, tk);
  1632. t = tkcfirsttag(c->head, f->obj);
  1633. if(t == nil)
  1634. return nil;
  1635. return tkvalue(val, "%s", tkcimethod[t->item->type].name);
  1636. }
  1637. static char*
  1638. tkcvsview(Tk *tk, char *arg, char **val, int nl, int *posn, int min, int max, int inc)
  1639. {
  1640. TkTop *t;
  1641. int top, bot, diff, amount;
  1642. char *e;
  1643. char buf[Tkmaxitem], *v;
  1644. diff = max-min;
  1645. if(*arg == '\0') {
  1646. if ( diff == 0 )
  1647. top = bot = 0;
  1648. else {
  1649. top = TKI2F(*posn-min)/diff;
  1650. bot = TKI2F(*posn+nl-min)/diff;
  1651. }
  1652. v = tkfprint(buf, top);
  1653. *v++ = ' ';
  1654. tkfprint(v, bot);
  1655. return tkvalue(val, "%s", buf);
  1656. }
  1657. t = tk->env->top;
  1658. arg = tkword(t, arg, buf, buf+sizeof(buf), nil);
  1659. if(strcmp(buf, "moveto") == 0) {
  1660. e = tkfrac(&arg, &top, nil);
  1661. if (e != nil)
  1662. return e;
  1663. *posn = min + TKF2I((top+1)*diff);
  1664. }
  1665. else
  1666. if(strcmp(buf, "scroll") == 0) {
  1667. arg = tkword(t, arg, buf, buf+sizeof(buf), nil);
  1668. amount = atoi(buf);
  1669. tkword(t, arg, buf, buf+sizeof(buf), nil);
  1670. if(buf[0] == 'p') /* Pages */
  1671. amount = amount * nl * 9 /10;
  1672. else if (inc > 0)
  1673. amount *= inc;
  1674. else
  1675. amount = amount * nl / 10;
  1676. *posn += amount;
  1677. }
  1678. else
  1679. return TkBadcm;
  1680. bot = max - nl;
  1681. if(*posn > bot)
  1682. *posn = bot;
  1683. if(*posn < min)
  1684. *posn = min;
  1685. tk->dirty = tkrect(tk, 0);
  1686. return nil;
  1687. }
  1688. static char*
  1689. tkcvsyview(Tk *tk, char *arg, char **val)
  1690. {
  1691. int si;
  1692. char *e;
  1693. TkCanvas *c = TKobj(TkCanvas, tk);
  1694. si = TKF2I(c->yscrolli);
  1695. e = tkcvsview(tk, arg, val, tk->act.height, &c->view.y, c->region.min.y, c->region.max.y, si);
  1696. tkcvssv(tk);
  1697. return e;
  1698. }
  1699. static char*
  1700. tkcvsxview(Tk *tk, char *arg, char **val)
  1701. {
  1702. int si;
  1703. char *e;
  1704. TkCanvas *c = TKobj(TkCanvas, tk);
  1705. si = TKF2I(c->xscrolli);
  1706. e = tkcvsview(tk, arg, val, tk->act.width, &c->view.x, c->region.min.x, c->region.max.x, si);
  1707. tkcvssh(tk);
  1708. return e;
  1709. }
  1710. /*
  1711. * return in posn the new view origin such that (preferably) smin and smax
  1712. * lie between cmin and cmax (cmin is the current view origin, and cmax the
  1713. * other end of the visible area).
  1714. * adjust posn (the view origin) so that (preferably) both smin and smax lie
  1715. * inside cmin to cmax. if both smin and smax cannot fit, then
  1716. * at least make sure that spref (smin<=spref<=smax) is visible.
  1717. * return 0 if no adjustment is required (the interval is already visible).
  1718. *
  1719. * attempt to make an adjustment as small as possible that
  1720. * fits these criteria.
  1721. */
  1722. static int
  1723. tkadjustvis(int *posn, int c0, int c1, int s0, int s1, int spref)
  1724. {
  1725. int d, v;
  1726. d = c1 - c0; /* visible width */
  1727. /*
  1728. * if requested range fits inside visible range,
  1729. * no adjustment is necessary
  1730. */
  1731. if (c0 <= s0 && s1 <= c1)
  1732. return 0;
  1733. /*
  1734. * if requested range fits, make it fully visible
  1735. */
  1736. if (s1 - s0 < d) {
  1737. if (s0 < c0)
  1738. v = s0;
  1739. else
  1740. v = s1 - d;
  1741. } else {
  1742. /*
  1743. * choose upper or lower end of requested range,
  1744. * depending on which end of requested area is already
  1745. * visible (if any).
  1746. */
  1747. if (c0 <= s1 && s1 < c1) { /* overlapping left of visible */
  1748. v = s1 - d;
  1749. if (v > spref)
  1750. v = spref;
  1751. }
  1752. else
  1753. if (c0 <= s0 && s0 < c1) { /* overlapping right of visible */
  1754. v = s0;
  1755. if (v + d <= spref)
  1756. v = spref - d;
  1757. }
  1758. else
  1759. if (s1 < c0) { /* left of visible */
  1760. v = spref;
  1761. if (v + d > s1)
  1762. v = s1 - d;
  1763. }
  1764. else { /* right of visible */
  1765. v = spref - d;
  1766. if (v < s0)
  1767. v = s0;
  1768. }
  1769. }
  1770. *posn = v;
  1771. return 1;
  1772. }
  1773. static void
  1774. tkcvsseerect(Tk *tk, Rectangle r, Point p)
  1775. {
  1776. TkCanvas *c;
  1777. int scrollh, scrollv;
  1778. c = TKobj(TkCanvas, tk);
  1779. scrollh = tkadjustvis(&c->view.x, c->view.x, c->view.x + tk->act.width,
  1780. r.min.x, r.max.x, p.x);
  1781. scrollv = tkadjustvis(&c->view.y, c->view.y, c->view.y + tk->act.height,
  1782. r.min.y, r.max.y, p.y);
  1783. if (scrollh)
  1784. tkcvssh(tk);
  1785. if (scrollv)
  1786. tkcvssv(tk);
  1787. if (scrollh || scrollv)
  1788. tk->dirty = tkrect(tk, 0);
  1789. }
  1790. static char*
  1791. tkcvssee(Tk *tk, char *arg, char **val)
  1792. {
  1793. Rectangle r;
  1794. int n, coords[4];
  1795. char *e;
  1796. USED(val);
  1797. n = 0;
  1798. while (n < 4) {
  1799. if (*arg == '\0')
  1800. break;
  1801. e = tkfracword(tk->env->top, &arg, &coords[n++], nil);
  1802. if (e != nil)
  1803. return e;
  1804. }
  1805. if (n != 2 && n != 4)
  1806. return TkFewpt;
  1807. r.min.x = TKF2I(coords[0]);
  1808. r.min.y = TKF2I(coords[1]);
  1809. if (n == 4) {
  1810. r.max.x = TKF2I(coords[2]);
  1811. r.max.y = TKF2I(coords[3]);
  1812. } else
  1813. r.max = r.min;
  1814. r = canonrect(r);
  1815. /*
  1816. * XXX should intersect r with scrollregion here, as you shouldn't
  1817. * be able to display things outside the scroll region. (??)
  1818. */
  1819. tkcvsseerect(tk, r, r.min);
  1820. return nil;
  1821. }
  1822. static void
  1823. tkcvsseesub(Tk *tk, Rectangle *rr, Point *pp)
  1824. {
  1825. Rectangle r;
  1826. Point p;
  1827. TkCanvas *c;
  1828. c = TKobj(TkCanvas, tk);
  1829. r = rectaddpt(*rr, c->view);
  1830. p = addpt(*pp, c->view);
  1831. tkcvsseerect(tk, r, p);
  1832. *rr = rectsubpt(r, c->view);
  1833. *pp = subpt(p, c->view);
  1834. }
  1835. static void
  1836. tkcvsgetimgs(Tk* tk, Image **image, Image **mask)
  1837. {
  1838. TkCanvas *c;
  1839. c = TKobj(TkCanvas, tk);
  1840. *image = c->image;
  1841. *mask = c->mask; /* XXX this is wrong - the mask image has nothing to do with the main image */
  1842. }
  1843. TkCimeth tkcimethod[] =
  1844. {
  1845. "line", tkcvslinecreat,
  1846. tkcvslinedraw,
  1847. tkcvslinefree,
  1848. tkcvslinecoord,
  1849. tkcvslinecget,
  1850. tkcvslineconf,
  1851. tkcvslinehit,
  1852. "text", tkcvstextcreat,
  1853. tkcvstextdraw,
  1854. tkcvstextfree,
  1855. tkcvstextcoord,
  1856. tkcvstextcget,
  1857. tkcvstextconf,
  1858. nil,
  1859. "rectangle", tkcvsrectcreat,
  1860. tkcvsrectdraw,
  1861. tkcvsrectfree,
  1862. tkcvsrectcoord,
  1863. tkcvsrectcget,
  1864. tkcvsrectconf,
  1865. nil,
  1866. "oval", tkcvsovalcreat,
  1867. tkcvsovaldraw,
  1868. tkcvsovalfree,
  1869. tkcvsovalcoord,
  1870. tkcvsovalcget,
  1871. tkcvsovalconf,
  1872. tkcvsovalhit,
  1873. "bitmap", tkcvsbitcreat,
  1874. tkcvsbitdraw,
  1875. tkcvsbitfree,
  1876. tkcvsbitcoord,
  1877. tkcvsbitcget,
  1878. tkcvsbitconf,
  1879. nil,
  1880. "polygon", tkcvspolycreat,
  1881. tkcvspolydraw,
  1882. tkcvspolyfree,
  1883. tkcvspolycoord,
  1884. tkcvspolycget,
  1885. tkcvspolyconf,
  1886. tkcvspolyhit,
  1887. "window", tkcvswindcreat,
  1888. tkcvswinddraw,
  1889. tkcvswindfree,
  1890. tkcvswindcoord,
  1891. tkcvswindcget,
  1892. tkcvswindconf,
  1893. nil,
  1894. "image", tkcvsimgcreat,
  1895. tkcvsimgdraw,
  1896. tkcvsimgfree,
  1897. tkcvsimgcoord,
  1898. tkcvsimgcget,
  1899. tkcvsimgconf,
  1900. nil,
  1901. "arc", tkcvsarccreat,
  1902. tkcvsarcdraw,
  1903. tkcvsarcfree,
  1904. tkcvsarccoord,
  1905. tkcvsarccget,
  1906. tkcvsarcconf,
  1907. nil,
  1908. nil
  1909. };
  1910. static
  1911. TkCmdtab tkcanvcmd[] =
  1912. {
  1913. "addtag", tkcvsaddtag,
  1914. "bbox", tkcvsbbox,
  1915. "bind", tkcvsbind,
  1916. "cget", tkcvscget,
  1917. "configure", tkcvsconf,
  1918. "create", tkcvscreate,
  1919. "canvasx", tkcvscanvx,
  1920. "canvasy", tkcvscanvy,
  1921. "coords", tkcvscoords,
  1922. "dchars", tkcvsdchars,
  1923. "delete", tkcvsdelete,
  1924. "dtag", tkcvsdtag,
  1925. "find", tkcvsfind,
  1926. "focus", tkcvsfocus,
  1927. "gettags", tkcvsgettags,
  1928. "grab", tkcvsgrab,
  1929. "icursor", tkcvsicursor,
  1930. "insert", tkcvsinsert,
  1931. "index", tkcvsindex,
  1932. "itemcget", tkcvsitemcget,
  1933. "itemconfigure", tkcvsitemconf,
  1934. "lower", tkcvslower,
  1935. "move", tkcvsmove,
  1936. "raise", tkcvsraise,
  1937. "screenx", tkcvsscreenx,
  1938. "screeny", tkcvsscreeny,
  1939. "see", tkcvssee,
  1940. "select", tkcvsselect,
  1941. "scale", tkcvsscale,
  1942. "type", tkcvstype,
  1943. "yview", tkcvsyview,
  1944. "xview", tkcvsxview,
  1945. nil
  1946. };
  1947. TkMethod canvasmethod = {
  1948. "canvas",
  1949. tkcanvcmd,
  1950. tkfreecanv,
  1951. tkdrawcanv,
  1952. tkcvsgeom,
  1953. tkcvsgetimgs,
  1954. tkcvsfocusorder,
  1955. tkcvsdirty,
  1956. tkcvsrelpos,
  1957. tkcvsevent,
  1958. tkcvsseesub,
  1959. tkcvsinwindow,
  1960. nil,
  1961. tkcvsforgetsub,
  1962. };