1 /*
2 * src/editTool.c, part of Complete Goban (game program)
3 * Copyright (C) 1995 William Shubert
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <wms.h>
8 #include <wms/str.h>
9 #include <wms/clp.h>
10 #include <but/but.h>
11 #include <abut/msg.h>
12 #include <but/text.h>
13 #include <abut/term.h>
14 #include <abut/fsel.h>
15 #include <abut/swin.h>
16 #include <but/radio.h>
17 #include <but/plain.h>
18 #include <but/canvas.h>
19 #include <but/ctext.h>
20 #include "cgoban.h"
21 #include "editTool.h"
22 #include "msg.h"
23 #include "sgfMap.h"
24 #include "sgf.h"
25 #include "help.h"
26
27
28 /**********************************************************************
29 * Forward declarations
30 **********************************************************************/
31 static ButOut unmap(ButWin *win);
32 static ButOut map(ButWin *win);
33 static ButOut resize(ButWin *win);
34 static ButOut iResize(ButWin *win);
35 static ButOut mapResize(ButWin *win);
36 static ButOut destroy(ButWin *win);
37 static ButOut newTool(But *but, int val);
38 static ButOut windowQuit(ButWin *win);
39 static ButOut mapCallback(But *but, int newNodeNum);
40 static ButOut cutPressed(But *but);
41 static ButOut movePressed(But *but);
42 static void updateTreeButtons(EditToolWin *etw);
43
44
45 /**********************************************************************
46 * Functions
47 **********************************************************************/
48 #define editW(bw, fontH) ((fontH*2 + bw*4) * editTool_max + bw * 4)
49
50
editToolWin_init(EditToolWin * etw,Cgoban * cg,Sgf * sgf,void (* quitRequested)(void * packet),ButOut (* newToolCallback)(void * packet),ButOut (* newActiveNode)(void * packet,int nodeNum),void * packet)51 void editToolWin_init(EditToolWin *etw, Cgoban *cg, Sgf *sgf,
52 void (*quitRequested)(void *packet),
53 ButOut (*newToolCallback)(void *packet),
54 ButOut (*newActiveNode)(void *packet,
55 int nodeNum),
56 void *packet) {
57 static const ButKey shiftUpKeys[] = {{XK_Up, ShiftMask, ShiftMask},
58 {0,0,0}};
59 static const ButKey shiftDownKeys[] = {{XK_Down, ShiftMask, ShiftMask},
60 {0,0,0}};
61 int w, h, minW, minH;
62 But *b;
63 int i, fontH;
64 bool err;
65
66 MAGIC_SET(etw);
67 etw->cg = cg;
68 etw->modified = FALSE;
69 fontH = butEnv_fontH(cg->env, 0);
70 minW = editW(butEnv_stdBw(cg->env), fontH);
71 minH = minW * 0.70710678 + 0.5;
72 w = (fontH * clp_getDouble(cg->clp, "edit.toolW") + 0.5);
73 h = (fontH * clp_getDouble(cg->clp, "edit.toolH") + 0.5);
74 if (w < minW)
75 w = minW;
76 if (h < minH)
77 h = minH;
78 etw->toolWin = butWin_iCreate(etw, cg->env, "Cgoban Tools", w, h,
79 &etw->toolIWin, FALSE, 48, 48, unmap, map,
80 resize, iResize, destroy);
81 i = clp_iGetInt(cg->clp, "edit.toolX", &err);
82 if (!err)
83 butWin_setX(etw->toolWin, i);
84 i = clp_iGetInt(cg->clp, "edit.toolY", &err);
85 if (!err)
86 butWin_setY(etw->toolWin, i);
87 butWin_setMinW(etw->toolWin, minW);
88 butWin_setMinH(etw->toolWin, minH);
89 butWin_setMaxW(etw->toolWin, 0);
90 butWin_setMaxH(etw->toolWin, 0);
91 butWin_setQuit(etw->toolWin, windowQuit);
92 butWin_activate(etw->toolWin);
93 etw->toolBg = butBoxFilled_create(etw->toolWin, 0, BUT_DRAWABLE);
94 butBoxFilled_setPixmaps(etw->toolBg, cg->bgLitPixmap, cg->bgShadPixmap,
95 cg->bgPixmap);
96 etw->toolIBg = butBoxFilled_create(etw->toolIWin, 0, BUT_DRAWABLE);
97 butBoxFilled_setPixmaps(etw->toolIBg, cg->bgLitPixmap, cg->bgShadPixmap,
98 cg->bgPixmap);
99 etw->toolIPic = toolPic_create(&cg->cgbuts, etw->toolIWin, 1, BUT_DRAWABLE);
100 etw->toolSel = butRadio_create(newTool, etw, etw->toolWin, 1,
101 BUT_PRESSABLE|BUT_DRAWABLE,
102 0, editTool_max);
103
104 etw->selDesc[editTool_play] = b =
105 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin, 2,
106 BUT_DRAWABLE|BUT_PRESSTHRU, 0);
107 grid_setStone(b, etw->lastColor = goStone_black, FALSE);
108 grid_setLineGroup(b, gridLines_none);
109 grid_setVersion(b, 0);
110
111 etw->selDesc[editTool_changeBoard] =
112 stoneGroup_create(&cg->cgbuts, etw->toolWin,
113 2, BUT_DRAWABLE|BUT_PRESSTHRU);
114
115 etw->selDesc[editTool_score] = b =
116 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin,
117 2, BUT_DRAWABLE|BUT_PRESSTHRU, 0);
118 grid_setStone(b, goStone_black, FALSE);
119 grid_setLineGroup(b, gridLines_none);
120 grid_setVersion(b, CGBUTS_YINYANG(1));
121
122 etw->selDesc[editTool_triangle] = b =
123 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin,
124 2, BUT_DRAWABLE|BUT_PRESSTHRU, 0);
125 grid_setStone(b, goStone_black, FALSE);
126 grid_setLineGroup(b, gridLines_none);
127 grid_setMark(b, goMark_triangle, 0);
128
129 etw->selDesc[editTool_square] = b =
130 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin,
131 2, BUT_DRAWABLE|BUT_PRESSTHRU, 0);
132 grid_setStone(b, goStone_black, FALSE);
133 grid_setLineGroup(b, gridLines_none);
134 grid_setMark(b, goMark_square, 0);
135
136 etw->selDesc[editTool_circle] = b =
137 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin,
138 2, BUT_DRAWABLE|BUT_PRESSTHRU, 0);
139 grid_setStone(b, goStone_black, FALSE);
140 grid_setLineGroup(b, gridLines_none);
141 grid_setMark(b, goMark_circle, 0);
142
143 etw->selDesc[editTool_letter] = b =
144 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin,
145 2, BUT_DRAWABLE|BUT_PRESSTHRU, 0);
146 grid_setStone(b, goStone_black, FALSE);
147 grid_setLineGroup(b, gridLines_none);
148 grid_setMark(b, goMark_letter, 'A');
149 grid_setVersion(b, 1);
150
151 etw->selDesc[editTool_number] = b =
152 grid_create(&cg->cgbuts, NULL, NULL, etw->toolWin,
153 2, BUT_DRAWABLE|BUT_PRESSTHRU, 0);
154 grid_setStone(b, goStone_black, FALSE);
155 grid_setLineGroup(b, gridLines_none);
156 grid_setMark(b, goMark_number, 1);
157 grid_setVersion(b, 2);
158
159 etw->mapWin = abutSwin_create(etw, etw->toolWin, 1,
160 ABUTSWIN_LSLIDE|ABUTSWIN_BSLIDE,
161 mapResize);
162 etw->mapBg = butPixmap_create(etw->mapWin->win, 0, BUT_DRAWABLE,
163 cg->boardPixmap);
164 etw->sgfMap = sgfMap_create(&cg->cgbuts, mapCallback, etw,
165 etw->mapWin->win,
166 1, BUT_DRAWABLE|BUT_PRESSABLE, sgf);
167 etw->prevVar = butKeytrap_create(editToolWin_shiftUpPressed, etw,
168 etw->toolWin, BUT_DRAWABLE|BUT_PRESSABLE);
169 but_setKeys(etw->prevVar, shiftUpKeys);
170 etw->nextVar = butKeytrap_create(editToolWin_shiftDownPressed, etw,
171 etw->toolWin, BUT_DRAWABLE|BUT_PRESSABLE);
172 but_setKeys(etw->nextVar, shiftDownKeys);
173
174 etw->sgf = sgf;
175
176 etw->tool = editTool_play;
177
178 etw->toolBox = butBoxFilled_create(etw->toolWin, 1, BUT_DRAWABLE);
179 etw->toolName = butText_create(etw->toolWin, 2, BUT_DRAWABLE,
180 msg_toolNames[etw->tool],
181 butText_center);
182 butText_setFont(etw->toolName, 2);
183 etw->toolDesc1 = butText_create(etw->toolWin, 2, BUT_DRAWABLE,
184 msg_toolDesc1[etw->tool],
185 butText_center);
186 etw->toolDesc2 = butText_create(etw->toolWin, 2, BUT_DRAWABLE,
187 msg_toolDesc2[etw->tool],
188 butText_center);
189 etw->help = butCt_create(cgoban_createHelpWindow, &help_editTool,
190 etw->toolWin, 1,
191 BUT_DRAWABLE | BUT_PRESSABLE, msg_help);
192 etw->killNode = butCt_create(cutPressed, etw, etw->toolWin, 1,
193 BUT_DRAWABLE | BUT_PRESSABLE,
194 msg_killNode);
195 etw->moveNode = butCt_create(movePressed, etw, etw->toolWin, 1,
196 BUT_DRAWABLE | BUT_PRESSABLE,
197 msg_moveNode);
198
199 etw->quitRequested = quitRequested;
200 etw->newToolCallback = newToolCallback;
201 etw->mapCallback = newActiveNode;
202 etw->packet = packet;
203 updateTreeButtons(etw);
204 }
205
206
editToolWin_deinit(EditToolWin * etw)207 void editToolWin_deinit(EditToolWin *etw) {
208 int fontH;
209
210 assert(MAGIC(etw));
211 if (etw->toolWin != NULL) {
212 fontH = butEnv_fontH(etw->cg->env, 0);
213 clp_setInt(etw->cg->clp, "edit.toolX", butWin_x(etw->toolWin));
214 clp_setInt(etw->cg->clp, "edit.toolY", butWin_y(etw->toolWin));
215 clp_setDouble(etw->cg->clp, "edit.toolW",
216 (double)butWin_w(etw->toolWin) / (double)fontH);
217 clp_setDouble(etw->cg->clp, "edit.toolH",
218 (double)butWin_h(etw->toolWin) / (double)fontH);
219 butWin_setPacket(etw->toolWin, NULL);
220 butWin_destroy(etw->toolWin);
221 }
222 MAGIC_UNSET(etw);
223 }
224
225
unmap(ButWin * win)226 static ButOut unmap(ButWin *win) {
227 return(0);
228 }
229
230
map(ButWin * win)231 static ButOut map(ButWin *win) {
232 return(0);
233 }
234
235
resize(ButWin * win)236 static ButOut resize(ButWin *win) {
237 EditToolWin *etw = butWin_packet(win);
238 ButEnv *env = butWin_env(win);
239 int bw = butEnv_stdBw(env);
240 int fontH = butEnv_fontH(env, 0), font2H = butEnv_fontH(env, 2);
241 int butH;
242 int w = butWin_w(win), h = butWin_h(win);
243 EditTool tool;
244 int x, x2, y, toolW;
245
246 assert(MAGIC(etw));
247 butH = etw->cg->fontH * 2;
248 but_resize(etw->toolBg, 0, 0, w, h);
249 but_resize(etw->toolSel, bw * 2, bw * 2, w - bw * 4, fontH * 2 + bw * 4);
250 x2 = bw * 2;
251 toolW = fontH * 2;
252 for (tool = editTool_min; tool < editTool_max; ++tool) {
253 x = x2;
254 x2 = bw * 2 + ((tool + 1) * (w - bw * 4)) / editTool_max;
255 but_resize(etw->selDesc[tool], (x + x2 - toolW) / 2, bw*4, toolW, toolW);
256 }
257 y = fontH * 2 + bw * 6;
258 but_resize(etw->toolBox, bw * 2, y, w - bw * 4, bw * 4 + font2H + fontH * 2);
259 but_resize(etw->toolName, bw * 4, y += bw * 2, w - bw * 8, font2H);
260 but_resize(etw->toolDesc1, bw * 4, y += font2H, w - bw * 8, fontH);
261 but_resize(etw->toolDesc2, bw * 4, y += fontH, w - bw * 8, fontH);
262 but_resize(etw->help, bw*2, y += fontH + bw * 3, (w - bw * 6 + 1) / 3, butH);
263 but_resize(etw->killNode, bw*3 + (w - bw * 6 + 1) / 3, y,
264 w - bw * 6 - 2*(w - bw * 6 + 1) / 3, butH);
265 but_resize(etw->moveNode, w - bw * 2 - (w - bw * 6 + 1) / 3, y,
266 (w - bw * 6 + 1) / 3, butH);
267
268 y += butH + bw;
269 abutSwin_resize(etw->mapWin, bw * 2, y, w - bw * 4, h - bw * 2 - y,
270 (fontH * 3) / 2, fontH * 3);
271 sgfMap_resize(etw->sgfMap, 0, 0);
272 butCan_resizeWin(etw->mapWin->win, but_w(etw->sgfMap), but_h(etw->sgfMap),
273 TRUE);
274
275 return(0);
276 }
277
278
iResize(ButWin * win)279 static ButOut iResize(ButWin *win) {
280 EditToolWin *etw = butWin_packet(win);
281 int bw = butEnv_stdBw(win->env);
282
283 assert(MAGIC(etw));
284 but_resize(etw->toolIBg, 0, 0, butWin_w(win), butWin_h(win));
285 but_resize(etw->toolIPic, bw*2, bw*2, butWin_w(win) - bw*4,
286 butWin_h(win) - bw*4);
287 return(0);
288 }
289
290
mapResize(ButWin * win)291 static ButOut mapResize(ButWin *win) {
292 AbutSwin *swin = butWin_packet(win);
293 EditToolWin *etw;
294
295 assert(MAGIC(swin));
296 etw = swin->packet;
297 assert(MAGIC(etw));
298 but_resize(etw->mapBg, 0, 0, butWin_w(win), butWin_h(win));
299 return(0);
300 }
301
302
destroy(ButWin * win)303 static ButOut destroy(ButWin *win) {
304 EditToolWin *etw = butWin_packet(win);
305
306 if (etw) {
307 assert(MAGIC(etw));
308 clp_setInt(etw->cg->clp, "edit.toolX", butWin_x(win));
309 clp_setInt(etw->cg->clp, "edit.toolY", butWin_y(win));
310 etw->toolWin = NULL;
311 /* editToolWin_deinit(etw); */
312 }
313 return(0);
314 }
315
316
windowQuit(ButWin * win)317 static ButOut windowQuit(ButWin *win) {
318 EditToolWin *etw = butWin_packet(win);
319
320 assert(MAGIC(etw));
321 etw->quitRequested(etw->packet);
322 return(0);
323 }
324
325
newTool(But * but,int val)326 static ButOut newTool(But *but, int val) {
327 EditToolWin *etw;
328
329 etw = but_packet(but);
330 assert(MAGIC(etw));
331 if ((EditTool)val != etw->tool) {
332 etw->tool = (EditTool)val;
333 butText_set(etw->toolName, msg_toolNames[val]);
334 butText_set(etw->toolDesc1, msg_toolDesc1[val]);
335 butText_set(etw->toolDesc2, msg_toolDesc2[val]);
336 }
337 return(etw->newToolCallback(etw->packet));
338 }
339
340
editToolWin_newColor(EditToolWin * etw,GoStone color)341 void editToolWin_newColor(EditToolWin *etw, GoStone color) {
342 if (color != etw->lastColor) {
343 grid_setStone(etw->selDesc[editTool_play], etw->lastColor = color, FALSE);
344 }
345 }
346
347
editToolWin_newTool(EditToolWin * etw,EditTool tool,bool propagate)348 void editToolWin_newTool(EditToolWin *etw, EditTool tool, bool propagate) {
349 butRadio_set(etw->toolSel, tool, propagate);
350 }
351
352
mapCallback(But * but,int newNodeNum)353 static ButOut mapCallback(But *but, int newNodeNum) {
354 EditToolWin *etw = but_packet(but);
355 ButOut result;
356
357 assert(MAGIC(etw));
358 result = etw->mapCallback(etw->packet, newNodeNum);
359 updateTreeButtons(etw);
360 return(result);
361 }
362
363
editToolWin_newActiveNode(EditToolWin * etw,SgfElem * newNode)364 void editToolWin_newActiveNode(EditToolWin *etw, SgfElem *newNode) {
365 int w, h, loX, loY, hiX, hiY;
366 int aX, aY;
367 int slideX, slideY, newX, newY;
368
369 sgfMap_newActive(etw->sgfMap, newNode);
370 w = butWin_viewW(etw->mapWin->win);
371 h = butWin_viewH(etw->mapWin->win);
372 newX = slideX = butCan_xOff(etw->mapWin->win);
373 newY = slideY = butCan_yOff(etw->mapWin->win);
374 loX = slideX + (w + 1) / 4;
375 loY = slideY + (h + 1) / 4;
376 hiX = slideX + (w * 3 + 1) / 4;
377 hiY = slideY + (h * 3 + 1) / 4;
378 aX = sgfMap_activeCtrX(etw->sgfMap);
379 aY = sgfMap_activeCtrY(etw->sgfMap);
380 if (aX < loX) {
381 newX = aX - (w + 1) / 4;
382 if (newX < 0)
383 newX = 0;
384 } else if (aX > hiX) {
385 newX = aX - (w * 3 + 1) / 4;
386 if (newX + w > butWin_w(etw->mapWin->win))
387 newX = butWin_w(etw->mapWin->win) - w;
388 }
389 if (aY < loY) {
390 newY = aY - (h + 1) / 4;
391 if (newY < 0)
392 newY = 0;
393 } else if (aY > hiY) {
394 newY = aY - (h * 3 + 1) / 4;
395 if (newY + h > butWin_h(etw->mapWin->win))
396 newY = butWin_h(etw->mapWin->win) - h;
397 }
398 if ((newX != slideX) || (newY != slideY)) {
399 butCan_slide(etw->mapWin->win, newX, newY, TRUE);
400 }
401 updateTreeButtons(etw);
402 }
403
404
cutPressed(But * but)405 static ButOut cutPressed(But *but) {
406 EditToolWin *etw = but_packet(but);
407 SgfElem *deadElem, *newActive;
408 ButOut result;
409
410 assert(MAGIC(etw));
411 etw->modified = TRUE;
412 deadElem = etw->sgf->active->activeChild;
413 if (deadElem == NULL)
414 return(BUTOUT_ERR);
415 newActive = deadElem->sibling;
416 if (newActive) {
417 sgfMap_changeVar(etw->sgfMap, sgfMap_next);
418 } else {
419 for (newActive = etw->sgf->active->childH;
420 newActive && (newActive->sibling != deadElem);
421 newActive = newActive->sibling);
422 if (newActive)
423 sgfMap_changeVar(etw->sgfMap, sgfMap_prev);
424 }
425 etw->sgf->active->activeChild = deadElem;
426 assert(newActive != etw->sgf->active->activeChild);
427 assert(MAGICNULL(newActive));
428 sgfElem_destroyActiveChild(etw->sgf->active);
429 assert(MAGICNULL(newActive));
430 etw->sgf->active->activeChild = newActive;
431 sgfMap_remap(etw->sgfMap, etw->sgf);
432 butCan_resizeWin(etw->mapWin->win, but_w(etw->sgfMap), but_h(etw->sgfMap),
433 TRUE);
434 result = etw->mapCallback(etw->packet, etw->sgf->active->mapX);
435 updateTreeButtons(etw);
436 return(result);
437 }
438
439
movePressed(But * but)440 static ButOut movePressed(But *but) {
441 EditToolWin *etw = but_packet(but);
442 SgfElem *active, *loSwap, *hiSwap, *prevChild;
443
444 assert(MAGIC(etw));
445 etw->modified = TRUE;
446 active = etw->sgf->active;
447 assert(active->childH != active->childT);
448 assert(active->childH != NULL);
449 hiSwap = active->activeChild;
450 if (active->childH == hiSwap) {
451 loSwap = hiSwap;
452 hiSwap = loSwap->sibling;
453 } else {
454 for (loSwap = active->childH;
455 loSwap->sibling != hiSwap;
456 loSwap = loSwap->sibling)
457 assert(MAGIC(loSwap));
458 }
459 if (active->childH == loSwap) {
460 active->childH = hiSwap;
461 } else {
462 for (prevChild = active->childH;
463 prevChild->sibling != loSwap;
464 prevChild = prevChild->sibling);
465 prevChild->sibling = hiSwap;
466 }
467 loSwap->sibling = hiSwap->sibling;
468 hiSwap->sibling = loSwap;
469 if (active->childT == hiSwap)
470 active->childT = loSwap;
471 sgfMap_remap(etw->sgfMap, etw->sgf);
472 butCan_resizeWin(etw->mapWin->win, but_w(etw->sgfMap), but_h(etw->sgfMap),
473 TRUE);
474 return(0);
475 }
476
477
editToolWin_nodeAdded(EditToolWin * etw,SgfElem * newNode)478 void editToolWin_nodeAdded(EditToolWin *etw, SgfElem *newNode) {
479 bool addSuccessful;
480
481 addSuccessful = sgfMap_newNode(etw->sgfMap, newNode);
482 if (!addSuccessful) {
483 sgfMap_remap(etw->sgfMap, etw->sgf);
484 butCan_resizeWin(etw->mapWin->win, but_w(etw->sgfMap), but_h(etw->sgfMap),
485 TRUE);
486 }
487 updateTreeButtons(etw);
488 }
489
490
editToolWin_shiftUpPressed(But * but,bool press)491 ButOut editToolWin_shiftUpPressed(But *but, bool press) {
492 EditToolWin *etw = but_packet(but);
493
494 assert(MAGIC(etw));
495 if (press) {
496 if (sgfMap_changeVar(etw->sgfMap, sgfMap_prev))
497 return(0);
498 else
499 return(BUTOUT_ERR);
500 } else
501 return(0);
502 }
503
504
editToolWin_shiftDownPressed(But * but,bool press)505 ButOut editToolWin_shiftDownPressed(But *but, bool press) {
506 EditToolWin *etw = but_packet(but);
507
508 assert(MAGIC(etw));
509 if (press) {
510 if (sgfMap_changeVar(etw->sgfMap, sgfMap_next))
511 return(0);
512 else
513 return(BUTOUT_ERR);
514 } else
515 return(0);
516 }
517
518
updateTreeButtons(EditToolWin * etw)519 static void updateTreeButtons(EditToolWin *etw) {
520 if (etw->sgf->active->childH) {
521 but_setFlags(etw->killNode, BUT_PRESSABLE);
522 if (etw->sgf->active->childH == etw->sgf->active->childT) {
523 but_setFlags(etw->moveNode, BUT_NOPRESS);
524 } else {
525 but_setFlags(etw->moveNode, BUT_PRESSABLE);
526 }
527 } else {
528 but_setFlags(etw->killNode, BUT_NOPRESS);
529 but_setFlags(etw->moveNode, BUT_NOPRESS);
530 }
531 }
532