1 /*
2 Copyright (C) 2019-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 /*
7 	WARNING: This file was generated by the dkct program (see
8 	http://dktools.sourceforge.net/ for details).
9 	Changes you make here will be lost if dkct is run again!
10 	You should modify the original source and run dkct on it.
11 	Original source: WxdkdrawFrameTools.cpt
12 */
13 
14 /**	@file WxdkdrawFrameTools.cpp The WxdkdrawFrameTools module.
15 */
16 
17 
18 #include <wxdkdraw/wxdkdraw.h>
19 
20 #ifndef	WXDKDRAWAPPH_INCLUDED
21 #include <wxdkdraw/WxdkdrawApp.h>
22 #endif
23 #ifndef	WXDKDRAWFRAME_H_INCLUDED
24 #include <wxdkdraw/WxdkdrawFrame.h>
25 #endif
26 
27 
28 
29 
30 
31 
32 /*	IMPORTANT: Number and order of entries here must match the order in the
33 	m_iv member array and the iv_keys array below!
34 */
35 /**	Default values for the integer array.
36 */
37 static const int default_values[] = {
38 /* IVI_BORDER_RED		*/		236 ,
39 /* IVI_BORDER_GREEN		*/		236 ,
40 /* IVI_BORDER_BLUE		*/		255 ,
41 /* IVI_BG_RED */				242 ,
42 /* IVI_BG_GREEN */				242 ,
43 /* IVI_BG_BLUE */				242 ,
44 /* IVI_GRID_RED */				202 ,
45 /* IVI_GRID_GREEN */			202 ,
46 /* IVI_GRID_BLUE */				230 ,
47 /* IVI_PH_RED */				255 ,
48 /* IVI_PH_GREEN */				214 ,
49 /* IVI_PH_BLUE */				  0 ,
50 /* IVI_M_COPY_RED */			  0 ,
51 /* IVI_M_COPY_GREEN */			143 ,
52 /* IVI_M_COPY_BLUE */			  0 ,
53 /* IVI_M_MOVE_RED */			  0 ,
54 /* IVI_M_MOVE_GREEN */			  0 ,
55 /* IVI_M_MOVE_BLUE */			204 ,
56 /* IVI_M_DEL_RED */				204 ,
57 /* IVI_M_DEL_GREEN */			  0 ,
58 /* IVI_M_DEL_BLUE */			  0 ,
59 /* IVI_M_GROUP_RED */			  0 ,
60 /* IVI_M_GROUP_GREEN */			  0 ,
61 /* IVI_M_GROUP_BLUE */			  0 ,
62 /* IVI_MISSIMG_RED */			204 ,
63 /* IVI_MISSIMG_GREEN */			  0 ,
64 /* IVI_MISSIMG_BLUE */			  0 ,
65 /* IVI_XS_SUBSEGS */			  4 ,
66 /* IVI_FONT_EXACT */			  0 ,
67 /* IVI_DOT_DIAMETER_FILLED */	  8 ,
68 /* IVI_DOT_DIAMETER_WHITE */	 10 ,
69 /* IVI_ARROWHEAD_LENGTH */		 16 ,
70 /* IVI_ARROWHEAD_WIDTH */		  8 ,
71 /* IVI_STYLE_VALUE */			  4 ,
72 /* IVI_MITER_LIMIT */			  8 ,
73 /* IVI_REDUCE_MARKUP_POINTS */	  1 ,
74 /* IVI_D_LAYER */				  0 ,
75 /* IVI_D_LINE_COL_RED */		  0 ,
76 /* IVI_D_LINE_COL_GREEN */		  0 ,
77 /* IVI_D_LINE_COL_BLUE */		  0 ,
78 /* IVI_D_LINEWIDTH */			  2 ,
79 /* IVI_D_LINESTYLE */			  WXD_LS_SOLID ,
80 /* IVI_D_STYLE_VALUE */			  4 ,
81 /* IVI_D_JOIN_STYLE */			  WXD_LJ_MITERED ,
82 /* IVI_D_MITER_LIMIT */			  8 ,
83 /* IVI_D_CAP_STYLE */			  WXD_LC_BUTTED ,
84 /* IVI_D_AHF_TYPE */			  0 ,
85 /* IVI_D_AHF_LENGTH */			 16 ,
86 /* IVI_D_AHF_WIDTH */			  8 ,
87 /* IVI_D_AHB_TYPE */			  0 ,
88 /* IVI_D_AHB_LENGTH */			 16 ,
89 /* IVI_D_AHB_WIDTH */			  8 ,
90 /* IVI_D_FILL_COL_RED */		255 ,
91 /* IVI_D_FILL_COL_GREEN */		255 ,
92 /* IVI_D_FILL_COL_BLUE */		255 ,
93 /* IVI_D_FILL_STYLE */			  WXD_FS_NONE ,
94 /* IVI_D_TEXT_LATEX */			  1 ,
95 /* IVI_D_TEXT_ALIGN */			  WXD_TEXT_ALIGN_LEFT ,
96 /* IVI_D_TEXT_FONT */			  0 ,
97 /* IVI_D_TEXT_SIZE */			 12 ,
98 /* IVI_C_GRID */				  1 ,
99 /* IVI_C_PH */					  0 ,
100 /* IVI_C_COR_POSITION */		  1 ,
101 };
102 /*	IMPORTANT: Number and order of entries here must match the order in the
103 	m_iv member array and the iv_keys array below!
104 */
105 
106 
107 
108 /*	IMPORTANT: Number and order of entries here must match the
109 	order in the default_values and m_iv arrays!
110 */
111 /**	Keys to save and restore the int values.
112 */
113 static const wxChar * const iv_keys[] = {
114 /* 0 */
115 wxT("colour.border.red"),
116 
117 /* 1 */
118 wxT("colour.border.green"),
119 
120 /* 2 */
121 wxT("colour.border.blue"),
122 
123 /* 3 */
124 wxT("colour.background.red"),
125 
126 /* 4 */
127 wxT("colour.background.blue"),
128 
129 /* 5 */
130 wxT("colour.background.green"),
131 
132 /* 6 */
133 wxT("colour.grid.red"),
134 
135 /* 7 */
136 wxT("colour.grid.green"),
137 
138 /* 8 */
139 wxT("colour.grid.blue"),
140 
141 /* 9 */
142 wxT("colour.placement-help.red"),
143 
144 /* 10 */
145 wxT("colour.placement-help.green"),
146 
147 /* 11 */
148 wxT("colour.placement-help.blue"),
149 
150 /* 12 */
151 wxT("colour.modify.copy.red"),
152 
153 /* 13 */
154 wxT("colour.modify.copy.green"),
155 
156 /* 14 */
157 wxT("colour.modify.copy.blue"),
158 
159 /* 15 */
160 wxT("colour.modify.move.red"),
161 
162 /* 16 */
163 wxT("colour.modify.move.green"),
164 
165 /* 17 */
166 wxT("colour.modify.move.blue"),
167 
168 /* 18 */
169 wxT("colour.modify.delete.red"),
170 
171 /* 19 */
172 wxT("colour.modify.delete.green"),
173 
174 /* 20 */
175 wxT("colour.modify.delete.blue"),
176 
177 /* 21 */
178 wxT("colour.modify.group.red"),
179 
180 /* 22 */
181 wxT("colour.modify.group.green"),
182 
183 /* 23 */
184 wxT("colour.modify.group.blue"),
185 
186 /* 24 */
187 wxT("colour.markup.missing-image.red"),
188 
189 /* 25 */
190 wxT("colour.markup.missing-image.green"),
191 
192 /* 26 */
193 wxT("colour.markup.missing-image.blue"),
194 
195 /* 27 */
196 wxT("config.x-spline.sub-segments"),
197 
198 /* 28 */
199 wxT("config.text.font.exact"),
200 
201 /* 29 */
202 wxT("config.dot.filled.diameter"),
203 
204 /* 30 */
205 wxT("config.dot.white.diameter"),
206 
207 /* 31 */
208 wxT("config.arrowhead.length"),
209 
210 /* 32 */
211 wxT("config.arrowhead.width"),
212 
213 /* 33 */
214 wxT("config.line.dash.length"),
215 
216 /* 34 */
217 wxT("config.join.miter-limit"),
218 
219 /* 35 */
220 wxT("config.markup-point.reduce-size"),
221 
222 /* 36 */
223 wxT("default.layer"),
224 
225 /* 37 */
226 wxT("default.colour.stroke.red"),
227 
228 /* 38 */
229 wxT("default.colour.stroke.green"),
230 
231 /* 39 */
232 wxT("default.colour.stroke.blue"),
233 
234 /* 40 */
235 wxT("default.line.width"),
236 
237 /* 41 */
238 wxT("default.line.style"),
239 
240 /* 42 */
241 wxT("default.line.dash.length"),
242 
243 /* 43 */
244 wxT("default.join.style"),
245 
246 /* 44 */
247 wxT("default.join.miter-limit"),
248 
249 /* 45 */
250 wxT("default.cap.style"),
251 
252 /* 46 */
253 wxT("default.arrowhead.forward.type"),
254 
255 /* 47 */
256 wxT("default.arrowhead.forward.length"),
257 
258 /* 48 */
259 wxT("default.arrowhead.forward.width"),
260 
261 /* 49 */
262 wxT("default.arrowhead.backward.type"),
263 
264 /* 50 */
265 wxT("default.arrowhead.backward.length"),
266 
267 /* 51 */
268 wxT("default.arrowhead.backward.width"),
269 
270 /* 52 */
271 wxT("default.colour.fill.red"),
272 
273 /* 53 */
274 wxT("default.colour.fill.green"),
275 
276 /* 54 */
277 wxT("default.colour.fill.blue"),
278 
279 /* 55 */
280 wxT("default.fill.style"),
281 
282 /* 56 */
283 wxT("default.text.latex"),
284 
285 /* 57 */
286 wxT("default.text.align"),
287 
288 /* 58 */
289 wxT("default.text.font"),
290 
291 /* 59 */
292 wxT("default.text.size"),
293 
294 /* 60 */
295 wxT("config.grid.enable"),
296 
297 /* 61 */
298 wxT("config.placement-help.enable"),
299 
300 /* 62 */
301 wxT("config.zoom-out.correct-position"),
302 
303 NULL
304 
305 };
306 /*	IMPORTANT: Number and order of entries here must match the
307 	order in the default_values and m_iv arrays!
308 */
309 
310 
311 
312 /**	Correct given int value v to a range specified by minimum and maximum.
313 	@param	min	Range minimum.
314 	@param	max	Range maximum.
315 	@param	v	Value to correct if necessary.
316 	@return	Corrected value.
317 */
318 static
319 int
i_to_range(int min,int max,int v)320 i_to_range(int min, int max, int v)
321 {
322 	if (min > v) { v = min; }
323 	if (max < v) { v = max; }
324 	return v;
325 }
326 
327 
328 
329 /**	Correct given int value v to an unsigned range specified by minimum
330 	and maximum.
331 	@param	min	Range minimum.
332 	@param	max	Range maximum.
333 	@param	v	Value to correct if necessary.
334 	@return	Corrected value.
335 */
336 static
337 unsigned
u_to_range(unsigned min,unsigned max,int v)338 u_to_range(unsigned min, unsigned max, int v)
339 {
340 	unsigned back;
341 
342 	if (0 <= v) {
343 		back = (unsigned)v;
344 	}
345 	else {
346 		back = 0U;
347 	}
348 	if (min > back) { back = min; }
349 	if (max < back) { back = max; }
350 	return back;
351 }
352 
353 
354 
355 void
DefaultStyleToArray(void)356 WxdkdrawFrame::DefaultStyleToArray(void)
357 {
358 
359 	m_iv[IVI_D_LAYER] 			=	m_oStyle.lay;
360 	m_iv[IVI_D_LINE_COL_RED]	=	m_oStyle.sc[0] ;
361 	m_iv[IVI_D_LINE_COL_GREEN]	=	m_oStyle.sc[1] ;
362 	m_iv[IVI_D_LINE_COL_BLUE]	=	m_oStyle.sc[2] ;
363 	m_iv[IVI_D_LINEWIDTH]		=	m_oStyle.lw ;
364 	m_iv[IVI_D_LINESTYLE]		=	m_oStyle.ls ;
365 	m_iv[IVI_D_STYLE_VALUE]		=	m_oStyle.sl ;
366 	m_iv[IVI_D_JOIN_STYLE]		=	m_oStyle.js ;
367 	m_iv[IVI_D_MITER_LIMIT]		=	m_oStyle.ml ;
368 	m_iv[IVI_D_CAP_STYLE]		=	m_oStyle.cs ;
369 	m_iv[IVI_D_AHF_TYPE]		=	m_oStyle.aft ;
370 	m_iv[IVI_D_AHF_LENGTH]		=	m_oStyle.afl ;
371 	m_iv[IVI_D_AHF_WIDTH]		=	m_oStyle.afw ;
372 	m_iv[IVI_D_AHB_TYPE]		=	m_oStyle.abt ;
373 	m_iv[IVI_D_AHB_LENGTH]		=	m_oStyle.abl ;
374 	m_iv[IVI_D_AHB_WIDTH]		=	m_oStyle.abw ;
375 	m_iv[IVI_D_FILL_COL_RED]	=	m_oStyle.fc[0] ;
376 	m_iv[IVI_D_FILL_COL_GREEN]	=	m_oStyle.fc[1] ;
377 	m_iv[IVI_D_FILL_COL_BLUE]	=	m_oStyle.fc[2] ;
378 	m_iv[IVI_D_FILL_STYLE]		=	m_oStyle.fs ;
379 	m_iv[IVI_D_TEXT_LATEX]		=	m_oStyle.det.t.fl ;
380 	m_iv[IVI_D_TEXT_ALIGN]		=	m_oStyle.det.t.al ;
381 	m_iv[IVI_D_TEXT_FONT]		=	m_oStyle.det.t.find ;
382 	m_iv[IVI_D_TEXT_SIZE]		=	m_oStyle.det.t.fsz ;
383 
384 }
385 
386 
387 
388 void
DefaultStyleFromArray(void)389 WxdkdrawFrame::DefaultStyleFromArray(void)
390 {
391 
392 	m_oStyle.lay	=	(int16_t)i_to_range(
393 		DK4_I16_MIN, DK4_I16_MAX, m_iv[IVI_D_LAYER]
394 	);
395 	m_oStyle.sc[0]	=	(uint8_t)u_to_range(
396 		0U, 255U, m_iv[IVI_D_LINE_COL_RED]
397 	);
398 	m_oStyle.sc[1]	=	(uint8_t)u_to_range(
399 		0U, 255U, m_iv[IVI_D_LINE_COL_GREEN]
400 	);
401 	m_oStyle.sc[2]	=	(uint8_t)u_to_range(
402 		0U, 255U, m_iv[IVI_D_LINE_COL_BLUE]
403 	);
404 	m_oStyle.lw	=	(uint16_t)u_to_range(
405 		0U, DK4_U16_MAX, m_iv[IVI_D_LINEWIDTH]
406 	);
407 	m_oStyle.ls	=	(uint8_t)u_to_range(
408 		WXD_LS_SOLID, WXD_LS_DASH_DOT_DOT_DOT, m_iv[IVI_D_LINESTYLE]
409 	);
410 	m_oStyle.sl	=	(uint8_t)u_to_range(
411 		1U, 255U,	m_iv[IVI_D_STYLE_VALUE]
412 	);
413 	m_oStyle.js	=	(uint8_t)u_to_range(
414 		WXD_LJ_MITERED, WXD_LJ_BEVELED, m_iv[IVI_D_JOIN_STYLE]
415 	);
416 	m_oStyle.ml	=	(uint8_t)u_to_range(
417 		1U, 255U, m_iv[IVI_D_MITER_LIMIT]
418 	);
419 	m_oStyle.cs	=	(uint8_t)u_to_range(
420 		WXD_LC_BUTTED, WXD_LC_PROJECTING, m_iv[IVI_D_CAP_STYLE]
421 	);
422 	m_oStyle.aft	=	(uint8_t)u_to_range(
423 		0U, 29U, m_iv[IVI_D_AHF_TYPE]
424 	);
425 	m_oStyle.afl	=	(uint8_t)u_to_range(
426 		2U, 255U, m_iv[IVI_D_AHF_LENGTH]
427 	);
428 	m_oStyle.afw	=	(uint8_t)u_to_range(
429 		2U, 255U, m_iv[IVI_D_AHF_WIDTH]
430 	);
431 	m_oStyle.abt	=	(uint8_t)u_to_range(
432 		0U, 29U, m_iv[IVI_D_AHB_TYPE]
433 	);
434 	m_oStyle.abl	=	(uint8_t)u_to_range(
435 		2U, 255U, m_iv[IVI_D_AHB_LENGTH]
436 	);
437 	m_oStyle.abw	=	(uint8_t)u_to_range(
438 		2U, 255U, m_iv[IVI_D_AHB_WIDTH]
439 	);
440 	m_oStyle.fc[0]	=	(uint8_t)u_to_range(
441 		0U, 255U, m_iv[IVI_D_FILL_COL_RED]
442 	);
443 	m_oStyle.fc[1]	=	(uint8_t)u_to_range(
444 		0U, 255U, m_iv[IVI_D_FILL_COL_GREEN]
445 	);
446 	m_oStyle.fc[2]	=	(uint8_t)u_to_range(
447 		0U, 255U, m_iv[IVI_D_FILL_COL_BLUE]
448 	);
449 	m_oStyle.fs	=	(uint8_t)u_to_range(
450 		WXD_FS_NONE, WXD_FS_VERTICAL_TIRES, m_iv[IVI_D_FILL_STYLE]
451 	);
452 	m_oStyle.det.t.fl	=	(uint8_t)u_to_range(
453 		0U, 1U, m_iv[IVI_D_TEXT_LATEX]
454 	);
455 	m_oStyle.det.t.al	=	(uint8_t)u_to_range(
456 		WXD_TA_LEFT, WXD_TA_RIGHT, m_iv[IVI_D_TEXT_ALIGN]
457 	);
458 	m_oStyle.det.t.find	=	(uint8_t)u_to_range(
459 		0U, 34U, m_iv[IVI_D_TEXT_FONT]
460 	);
461 	m_oStyle.det.t.fsz	=	(uint16_t)u_to_range(
462 		1U, DK4_U16_MAX, m_iv[IVI_D_TEXT_SIZE]
463 	);
464 
465 }
466 
467 
468 
469 void
LoadDefaults(void)470 WxdkdrawFrame::LoadDefaults(void)
471 {
472 	DK4_MEMCPY(m_iv,default_values,((size_t)(IVI_MAX)*sizeof(int)));
473 }
474 
475 
476 
477 void
LoadConfiguration(void)478 WxdkdrawFrame::LoadConfiguration(void)
479 {
480 	LoadDefaults();
481 	DefaultStyleToArray();
482 	pAppHelp->GetMultiple(iv_keys ,m_iv, IVI_MAX);
483 	DefaultStyleFromArray();
484 	cbGridOnOff->SetValue((0 != m_iv[IVI_C_GRID]));
485 	cbPH->SetValue((0 != m_iv[IVI_C_PH]));
486 }
487 
488 
489 
490 void
SaveConfiguration(void)491 WxdkdrawFrame::SaveConfiguration(void)
492 {
493 	DefaultStyleToArray();
494 	m_iv[IVI_C_GRID] = ((cbGridOnOff->GetValue()) ? 1 : 0);
495 	m_iv[IVI_C_PH] = ((cbPH->GetValue()) ? 1 : 0);
496 	pAppHelp->SetMultiple(iv_keys ,m_iv, IVI_MAX);
497 }
498 
499 
500 
501 void
ResetConfiguration(void)502 WxdkdrawFrame::ResetConfiguration(void)
503 {
504 	LoadDefaults();
505 	wxdobj_obj_init(&m_oStyle, WXD_OT_TEXT, NULL);
506 }
507 
508 
509 
510 void
ColorModify(size_t ivi,int rdl)511 WxdkdrawFrame::ColorModify(size_t ivi, int rdl)
512 {
513 	wxColour		curcol(
514 							(unsigned char)(m_iv[ivi]),
515 							(unsigned char)(m_iv[ivi + 1]),
516 							(unsigned char)(m_iv[ivi + 2])
517 	);
518 	wxColourData	wxcd;
519 
520 	wxcd.SetColour(curcol);
521 	wxColourDialog    dlg(this, &wxcd);
522 
523 	if (wxID_OK == dlg.ShowModal()) {
524 		wxColour col = dlg.GetColourData().GetColour();
525 		m_iv[ivi    ] = col.Red();
526 		m_iv[ivi + 1] = col.Green();
527 		m_iv[ivi + 2] = col.Blue();
528 		wxdobj_drw_require_redraw(m_pDrw, rdl);
529 	}
530 
531 }
532 
533 
534 
535 void
ColorReset(size_t ivi,int rdl)536 WxdkdrawFrame::ColorReset(size_t ivi, int rdl)
537 {
538 
539 	DK4_MEMCPY(&(m_iv[ivi]),&(default_values[ivi]),(3*sizeof(int)));
540 	wxdobj_drw_require_redraw(m_pDrw, rdl);
541 
542 }
543 
544 
545 
546 bool
FindDirectoryForFile(wxChar * dnb,size_t dnsz,wxString & fn)547 WxdkdrawFrame::FindDirectoryForFile(wxChar *dnb, size_t dnsz, wxString & fn)
548 {
549 	wxChar const	*fnstr	=	NULL;
550 	wxChar const	*cwdstr	=	NULL;
551 	wxChar			*ptr	=	NULL;
552 	size_t			 lgt	=	(size_t)0U;
553 	bool			 back	=	false;
554 
555 	if ((NULL != dnb) && ((size_t)0U < dnsz)) {
556 		dnb[0] = wxT('\0');
557 		wxCStrData	strd = fn.c_str();
558 		fnstr = (wxChar const *)strd;
559 		if (NULL != fnstr) {
560 			lgt = dk4strx_len(fnstr);
561 			if ((size_t)0U < lgt) {
562 				if (lgt < dnsz) {
563 					dk4strx_cpy_s(dnb, dnsz, fnstr, NULL);
564 #if	DK4_HAVE_BACKSLASH_AS_SEP
565 					ptr = dk4strx_rchr(dnb, wxT('\\'));
566 #else
567 					ptr = dk4strx_rchr(dnb, wxT('/'));
568 #endif
569 					if (NULL != ptr) {
570 						*ptr = wxT('\0');
571 						back = true;
572 
573 					}
574 					else {
575 						wxString cwd = ::wxGetCwd();
576 						{
577 							wxCStrData	strwcd = cwd.c_str();
578 							{
579 								cwdstr = (wxChar const *)strwcd;
580 								if (NULL != cwdstr) {
581 									lgt = dk4strx_len(cwdstr);
582 									if ((size_t)0U < lgt) {
583 										if (lgt < dnsz) {
584 											dk4strx_cpy_s(dnb,dnsz,cwdstr,NULL);
585 											back = true;
586 
587 										}
588 										else {
589 											/* ERROR: CWD too long */
590 											dk4error_set_simple_error_code(
591 												&m_oErrorReport,
592 												WXD_E_CWD_TOO_LONG
593 											);
594 										}
595 									}
596 									else {
597 										/* ERROR: No current dir */
598 										dk4error_set_simple_error_code(
599 											&m_oErrorReport,
600 											WXD_E_NO_CWD
601 										);
602 									}
603 								}
604 								else {
605 									/* ERROR: No current dir */
606 									dk4error_set_simple_error_code(
607 										&m_oErrorReport, WXD_E_NO_CWD
608 									);
609 								}
610 							}
611 						}
612 					}
613 				}
614 				else {
615 					/* ERROR: Output file name too long */
616 					dk4error_set_simple_error_code(
617 						&m_oErrorReport, WXD_E_OUTPUT_FN_TOO_LONG
618 					);
619 				}
620 			}
621 			else {
622 				/* ERROR: Failed to find directory for file */
623 				dk4error_set_simple_error_code(
624 					&m_oErrorReport, WXD_E_OUTPUT_DIRNAME
625 				);
626 			}
627 		}
628 		else {
629 			/* ERROR: Failed to find directory for file */
630 			dk4error_set_simple_error_code(
631 				&m_oErrorReport, WXD_E_OUTPUT_DIRNAME
632 			);
633 		}
634 	}
635 	else {
636 	}
637 	return back;
638 }
639 
640 
641 
642 bool
SaveToFile(void)643 WxdkdrawFrame::SaveToFile(void)
644 {
645 	wxChar			 fnbuf[DK4_MAX_PATH];		/* File name current dir */
646 	wxdwr_status_t	 wrst;						/* Writer status */
647 	wxString		 sNewTitle = wxEmptyString;	/* New program window title */
648 	wxString		 sDlgTitle(sTexts[171]);	/* Dialog title */
649 	wxString		 sDlgTypes(sTexts[172]);	/* File type suffixes */
650 	FILE			*fipo;						/* File for output */
651 	int				 res;						/* Save operation result */
652 	bool			 cc = true;					/* Flag: Can continue */
653 	bool			 back	= false;
654 
655 	if (!(m_bHaveName)) {
656 #if	wxCHECK_VERSION(2, 9, 0)
657 		wxFileDialog dlg(
658 			this, sDlgTitle, m_sFileDir, m_sFileShort,
659 			sDlgTypes, (wxFD_SAVE | wxFD_OVERWRITE_PROMPT)
660 		);
661 #else
662 		wxFileDialog dlg(
663 			this, sDlgTitle, m_sFileDir, m_sFileShort,
664 			sDlgTypes, wxSAVE
665 		);
666 #endif
667 		if(wxID_OK == dlg.ShowModal()) {
668 			m_sFileFull = dlg.GetPath();
669 			m_sFileDir = dlg.GetDirectory();
670 			m_sFileShort = dlg.GetFilename();
671 			m_bHaveName = true;
672 			if (m_bModified) {
673 				sNewTitle.Append(sTexts[170]);
674 				sNewTitle.Append(m_sFileShort);
675 				SetTitle(sNewTitle);
676 			}
677 			else {
678 				SetTitle(m_sFileShort);
679 			}
680 			m_bUpdate = true;
681 		}
682 		else {
683 			cc = false;
684 		}
685 	}
686 	if (m_bHaveName && cc) {
687 		cc = FindDirectoryForFile(fnbuf, DK4_SIZEOF(fnbuf,wxChar), m_sFileFull);
688 		if (!(cc)) {
689 			/* ##### ERROR: Failed to find directory */
690 		}
691 	}
692 	if (m_bHaveName && cc) {
693 		wxFFile		wxff(m_sFileFull, wxT("w"));
694 		if (wxff.IsOpened()) {
695 			fipo = wxff.Detach();
696 			if (NULL != fipo) {
697 				back = true;
698 				wxdwr_status_init(&wrst, pAppHelp->GetWxEncoding());
699 				wrst.dirn = fnbuf;
700 				res = wxdwr_write_file(fipo, m_pDrw, &wrst);
701 				wrst.dirn = NULL;
702 				if (0 == res) {
703 					back = false;
704 					switch (wrst.ec) {
705 						case WXDWR_E_WRITE : {
706 							/* ERROR: Write operation failed */
707 							wxMessageBox(
708 								sTexts[204], sTexts[202],
709 								(wxOK | wxCENTRE | wxICON_ERROR)
710 							);
711 						} break;
712 						case WXDWR_E_STRING_TOO_LONG : {
713 							/* ERROR: String too long */
714 							if (NULL != wrst.str) {
715 								wxString msg = wxString(sTexts[205]);
716 								msg.Append(wxString(wrst.str));
717 								msg.Append(wxString(sTexts[206]));
718 								wxMessageBox(
719 									msg, sTexts[202],
720 									(wxOK | wxCENTRE | wxICON_ERROR)
721 								);
722 							}
723 							else {
724 								wxMessageBox(
725 									sTexts[207], sTexts[202],
726 									(wxOK | wxCENTRE | wxICON_ERROR)
727 								);
728 							}
729 						} break;
730 						case WXDWR_E_RECODE_TEXT : {
731 							/* ERROR: Failed to recode text */
732 							if (NULL != wrst.str) {
733 								wxString msg = wxString(sTexts[208]);
734 								msg.Append(wxString(wrst.str));
735 								msg.Append(wxString(sTexts[209]));
736 								wxMessageBox(
737 									msg, sTexts[202],
738 									(wxOK | wxCENTRE | wxICON_ERROR)
739 								);
740 							}
741 							else {
742 								wxMessageBox(
743 									sTexts[210], sTexts[202],
744 									(wxOK | wxCENTRE | wxICON_ERROR)
745 								);
746 							}
747 
748 						} break;
749 						case WXDWR_E_RECODE_FILENAME : {
750 							/* ERROR: Failed to recode file name */
751 							if (NULL != wrst.str) {
752 								wxString msg = wxString(sTexts[211]);
753 								msg.Append(wxString(wrst.str));
754 								msg.Append(wxString(sTexts[212]));
755 								wxMessageBox(
756 									msg, sTexts[202],
757 									(wxOK | wxCENTRE | wxICON_ERROR)
758 								);
759 							}
760 							else {
761 								wxMessageBox(
762 									sTexts[213], sTexts[202],
763 									(wxOK | wxCENTRE | wxICON_ERROR)
764 								);
765 							}
766 						} break;
767 						case WXDWR_E_STRING_EMPTY : {
768 							/* ERROR: Empty string not expected */
769 							wxMessageBox(
770 								sTexts[214], sTexts[202],
771 								(wxOK | wxCENTRE | wxICON_ERROR)
772 							);
773 						} break;
774 						default : {
775 							/* ERROR: Unknown reason */
776 							wxMessageBox(
777 								sTexts[215], sTexts[202],
778 								(wxOK | wxCENTRE | wxICON_ERROR)
779 							);
780 						} break;
781 					}
782 				}
783 #if	TRACE_DEBUG
784 				else {
785 				}
786 #endif
787 				if (0 != fclose(fipo)) {
788 					if (back) {
789 						/* ERROR: Failed to write to file */
790 						wxMessageBox(
791 							sTexts[204], sTexts[202],
792 							(wxOK | wxCENTRE | wxICON_ERROR)
793 						);
794 					}
795 					back = false;
796 				}
797 #if	TRACE_DEBUG
798 				else {
799 				}
800 #endif
801 			}
802 			else {
803 				/* ERROR: Failed to open file */
804 				wxMessageBox(
805 					sTexts[203], sTexts[202], (wxOK | wxCENTRE | wxICON_ERROR)
806 				);
807 			}
808 		}
809 		else {
810 			/* ERROR: Failed to open file */
811 			wxMessageBox(
812 				sTexts[203], sTexts[202], (wxOK | wxCENTRE | wxICON_ERROR)
813 			);
814 		}
815 		if (back) {
816 			SetTitle(m_sFileShort);
817 			SetModified(false);
818 		}
819 	}
820 #if	TRACE_DEBUG
821 	else {
822 	}
823 #endif
824 
825 	return back;
826 }
827 
828 
829 
830 void
SetModified(bool f)831 WxdkdrawFrame::SetModified(bool f)
832 {
833 
834 if (f != m_bModified) {
835 	if (f) {
836 		wxString	s	= wxEmptyString;
837 		s.Append(sTexts[170]);
838 		if (m_bHaveName) {
839 			s.Append(m_sFileShort);
840 		}
841 		else {
842 			s.Append(sTexts[18]);
843 		}
844 		SetTitle(s);
845 	}
846 	else {
847 		if (m_bHaveName) {
848 			SetTitle(m_sFileShort);
849 		}
850 		else {
851 			SetTitle(sTexts[18]);
852 		}
853 	}
854 	m_bModified = f;
855 	m_bUpdate = true;
856 }
857 
858 }
859 
860 
861 
862 
863 wxSize
ColourViewSize(void)864 WxdkdrawFrame::ColourViewSize(void)
865 {
866 int	sl = 20;
867 if (NULL != bFileOpen) {
868 	sl = (bFileOpen->GetClientSize()).GetHeight();
869 }
870 
871 return(wxSize(sl,sl));
872 }
873 
874 
875 
876 Wxd_drawing_t *
ReadDrawingFromFile(wxString & fn)877 WxdkdrawFrame::ReadDrawingFromFile(wxString & fn)
878 {
879 	wxChar		 	 dirnb[DK4_MAX_PATH];
880 	Wxd_drawing_t	*back	= NULL;		/* Function result */
881 	FILE			*fp		= NULL;		/* File to read from */
882 	bool			 haved	= false;	/* Have directory name */
883 
884 	wxFFile		wxff(fn);
885 	haved = FindDirectoryForFile(dirnb, DK4_SIZEOF(dirnb,wxChar), fn);
886 	if (wxff.IsOpened()) {
887 		fp = wxff.Detach();
888 		if (NULL != fp) {
889 
890 			wxdrd_status_init(&m_oStatusReader);
891 			if (haved) {
892 				m_oStatusReader.dirn = dirnb;
893 			}
894 			else {
895 				m_oStatusReader.dirn = NULL;
896 			}
897 			back = wxdrd_read_file(fp, &m_oStatusReader);
898 			m_oStatusReader.dirn = NULL;
899 			fclose(fp);
900 			if (NULL != back) {
901 				wxdobj_drw_set_xsubs(back, (size_t)(m_iv[IVI_XS_SUBSEGS]));
902 				wxdobj_bb_for_drawing(back);
903 			}
904 			else {
905 				/* ERROR: Failed to read file */
906 				dk4error_set_simple_error_code(
907 					&m_oErrorReport, WXD_E_FAILED_TO_READ_FILE
908 				);
909 			}
910 		}
911 		else {
912 			/* ERROR: Failed to open file */
913 			dk4error_set_simple_error_code(
914 				&m_oErrorReport, WXD_E_FAILED_TO_OPEN_FILE
915 			);
916 		}
917 	}
918 	else {
919 		/* ERROR: Failed to open file */
920 		dk4error_set_simple_error_code(
921 			&m_oErrorReport, WXD_E_FAILED_TO_OPEN_FILE
922 		);
923 	}
924 
925 	return back;
926 }
927 
928 
929 
930 void
UpdateImages(void)931 WxdkdrawFrame::UpdateImages(void)
932 {
933 	Wxd_object_t	*pobj;
934 	dk4sto_it_reset(m_pDrw->i_flat);
935 	do {
936 		pobj = (Wxd_object_t *)dk4sto_it_next(m_pDrw->i_flat);
937 		if (NULL != pobj) {
938 			if (WXD_OT_IMAGE == pobj->ot) {
939 				if (NULL != (pobj->det).i.fn) {
940 					if (NULL == (pobj->det).i.bm) {
941 						wxdobj_load_image(
942 							pobj,
943 							pAppHelp->GetDkEncoding(),
944 							pAppHelp->GetWxEncoding()
945 						);
946 					}
947 				}
948 			}
949 		}
950 	} while (NULL != pobj);
951 }
952 
953 
954 
955 void
DrawingLoaded(void)956 WxdkdrawFrame::DrawingLoaded(void)
957 {
958 	/*	No operation started on new drawing yet
959 	*/
960 	m_iState = S_NOOP;
961 	m_iWheelControl = 0;
962 	m_iWheelShift = 0;
963 	m_iWheelNormal = 0;
964 	m_pStyle = NULL;
965 	m_pCurrent = NULL;
966 	/*	Zoom factor and grid distances
967 	*/
968 	drawco->CalculateZoomFactor();
969 	{
970 		wxString s;
971 		s.Printf("%g", drawco->m_dZoom);
972 		lZoomPercent->SetLabel(s);
973 		lZoomPercent->Refresh();
974 		m_bUpdate = true;
975 	}
976 	/*	Update coefficients for fill patterns
977 	*/
978 	UpdateStipples();
979 	UpdateFonts();
980 	szTopBar->Layout();
981 	lZoomPercent->Refresh();
982 	UpdateImages();
983 	/*	Coordinates conversion coefficients
984 	*/
985 	drawco->CalculateConversionCoefficients();
986 
987 	/*	Grid setup to GUI
988 	*/
989 	if (NULL != m_pDrw) {
990 		if ((uint8_t)0U != m_pDrw->gridunit) {
991 			cbGridUnit->SetSelection(1);
992 		}
993 		else {
994 			cbGridUnit->SetSelection(0);
995 		}
996 		if ((uint8_t)0U != m_pDrw->gridbase) {
997 			cbGridBase->SetSelection(1);
998 		}
999 		else {
1000 			cbGridBase->SetSelection(0);
1001 		}
1002 		cbGridUnit->Refresh();
1003 		cbGridBase->Refresh();
1004 		m_bUpdate = true;
1005 	}
1006 
1007 	/*	Calculate grid
1008 	*/
1009 	drawco->CalculateGridDistances();
1010 
1011 	/*	Required width and height
1012 	*/
1013 
1014 	/*	Scrollbar positions
1015 	*/
1016 	AdjustScrollbars();
1017 
1018 	/*	GUI attributes object
1019 	*/
1020 	m_pStyle = NULL;
1021 	m_pCurrent = NULL;
1022 	m_iState = S_NOOP;
1023 	m_iWheelControl = 0;
1024 	m_iWheelShift = 0;
1025 	m_iWheelNormal = 0;
1026 	m_uCurrent = 0;
1027 	m_iObjToCreate = -1;
1028 	m_bSplineInterpolated = false;
1029 	m_bModified = false;
1030 	m_bMouseDiff = false;
1031 
1032 	drawco->Refresh();
1033 	m_bUpdate = true;
1034 }
1035 
1036 
1037 
1038 void
ModificationReportingAtEventEnd(void)1039 WxdkdrawFrame::ModificationReportingAtEventEnd(void)
1040 {
1041 	if (DK4_E_NONE == m_oErrorReport.ec) {
1042 		if (0 != m_oStatusReader.mod) {
1043 			SetModified();
1044 			wxMessageBox(
1045 				sTexts[600], sTexts[599],
1046 				(wxOK | wxCENTRE | wxICON_INFORMATION)
1047 			);
1048 		}
1049 	}
1050 }
1051 
1052 
1053 
1054 void
OnFirstIdle(void)1055 WxdkdrawFrame::OnFirstIdle(void)
1056 {
1057 	Wxd_drawing_t	*pDrw;
1058 
1059 
1060 	wxdrd_status_init(&m_oStatusReader);
1061 	dk4error_init(&m_oErrorReport);
1062 	m_pDrw = wxdobj_drw_new();
1063 	if (m_bHaveName) {
1064 		wxFileName	wxfn(m_sFileFull);
1065 		SetTitle(m_sFileShort);
1066 		if (wxfn.IsFileReadable()) {
1067 			pDrw = ReadDrawingFromFile(m_sFileFull);
1068 			if (NULL != pDrw) {
1069 				wxdobj_drw_delete(m_pDrw);
1070 				m_pDrw = pDrw;
1071 				m_bHaveName = true;
1072 				m_bUpdate = true;
1073 			}
1074 			else {
1075 				/* ERROR: Failed to read file, already reported */
1076 			}
1077 		}
1078 		else {
1079 			dk4error_set_simple_error_code(
1080 				&m_oErrorReport, WXD_E_FAILED_TO_OPEN_FILE
1081 			);
1082 		}
1083 	}
1084 #if	TRACE_DEBUG
1085 	else {
1086 	}
1087 #endif
1088 	/*	If drawing was read, set frame as active (ready for events).
1089 		Otherwise show error message and exit application.
1090 	*/
1091 	if (NULL != m_pDrw) {
1092 		m_bActive = true;
1093 		DrawingLoaded();
1094 		szTopBar->Layout();
1095 		SetStatusText(sTexts[531]);
1096 		Refresh();
1097 		Update();
1098 	}
1099 	else {
1100 		Close();
1101 	}
1102 	ModificationReportingAtEventEnd();
1103 	ErrorReportingAtEventEnd();
1104 	dk4error_init(&m_oErrorReport);
1105 
1106 	wxdrd_status_init(&m_oStatusReader);
1107 
1108 }
1109 
1110 
1111 
1112 static
i32_avg(int32_t a,int32_t b,dk4_er_t * erp)1113 int32_t	i32_avg(int32_t	a, int32_t b, dk4_er_t *erp)
1114 {
1115 	dk4_er_t	er;
1116 	int32_t		back	= (int32_t)0L;
1117 
1118 	dk4error_init(&er);
1119 	back = dk4ma_int32_t_add(a, b, &er) / ((int32_t)2L);
1120 	if (DK4_E_NONE != er.ec) {
1121 		dk4error_init(&er);
1122 		back = dk4ma_int32_t_add(
1123 			a,
1124 			(dk4ma_int32_t_sub(b, a, &er) / ((int32_t)2L)),
1125 			&er
1126 		);
1127 		if (DK4_E_NONE != er.ec) {
1128 			dk4error_copy(erp, &er);
1129 		}
1130 	}
1131 	return back;
1132 }
1133 
1134 
1135 
1136 void
CorrectCenterPointIfNecessary(void)1137 WxdkdrawFrame::CorrectCenterPointIfNecessary(void)
1138 {
1139 	dk4_er_t	er;
1140 	int32_t		xcmin;		/* Minimum value for center x position */
1141 	int32_t		xcmax;		/* Maximum value for center x position */
1142 	int32_t		ycmin;		/* Minimum value for center y position */
1143 	int32_t		ycmax;		/* Maximum value for center y position */
1144 	int32_t		deltax;		/* X difference border to center */
1145 	int32_t		deltay;		/* Y difference border to center */
1146 
1147 	dk4error_init(&er);
1148 	deltax = dk4ma_int32_from_double(
1149 		(
1150 			(16256000.0 * (double)((drawco->m_szDrawco).GetWidth()))
1151 			/ (2.0 * drawco->m_dZoom * (drawco->m_ptRes).x)
1152 		), &er
1153 	);
1154 	deltay = dk4ma_int32_from_double(
1155 		(
1156 			(16256000.0 * (double)((drawco->m_szDrawco).GetHeight()))
1157 			/ (2.0 * drawco->m_dZoom * (drawco->m_ptRes).y)
1158 		), &er
1159 	);
1160 	xcmin = dk4ma_int32_t_add(
1161 		dk4ma_int32_t_sub(
1162 			(m_pDrw->bb).xl,
1163 			dk4ma_int32_from_double((double)(m_pDrw->bleft), &er),
1164 			&er
1165 		),	deltax, &er
1166 	);
1167 	xcmax = dk4ma_int32_t_sub(
1168 		dk4ma_int32_t_add(
1169 			(m_pDrw->bb).xr,
1170 			dk4ma_int32_from_double((double)(m_pDrw->bright), &er),
1171 			&er
1172 		),	deltax, &er
1173 	);
1174 	ycmin = dk4ma_int32_t_add(
1175 		dk4ma_int32_t_sub(
1176 			(m_pDrw->bb).yb,
1177 			dk4ma_int32_from_double((double)(m_pDrw->bbottom), &er),
1178 			&er
1179 		),	deltay, &er
1180 	);
1181 	ycmax = dk4ma_int32_t_sub(
1182 		dk4ma_int32_t_add(
1183 			(m_pDrw->bb).yt,
1184 			dk4ma_int32_from_double((double)(m_pDrw->btop), &er),
1185 			&er
1186 		),	deltay, &er
1187 	);
1188 	if (DK4_E_NONE == er.ec) {
1189 		/*
1190 			X correction
1191 		*/
1192 		if (xcmax > xcmin) {
1193 			if (m_pDrw->cx < xcmin) {
1194 				m_pDrw->cx = xcmin;
1195 			}
1196 			else {
1197 				if (m_pDrw->cx > xcmax) {
1198 					m_pDrw->cx = xcmax;
1199 				}
1200 			}
1201 		}
1202 		else {
1203 			if (xcmax == xcmin) {
1204 				m_pDrw->cx = xcmin;
1205 			}
1206 			else {
1207 				xcmin = i32_avg((m_pDrw->bb).xl, (m_pDrw->bb).xr, &er);
1208 				if (DK4_E_NONE == er.ec) {
1209 					m_pDrw->cx = xcmin;
1210 				}
1211 			}
1212 		}
1213 		/*
1214 			Y correction
1215 		*/
1216 		if (ycmax > ycmin) {
1217 			if (m_pDrw->cy < ycmin) {
1218 				m_pDrw->cy = ycmin;
1219 			}
1220 			else {
1221 				if (m_pDrw->cy > ycmax) {
1222 					m_pDrw->cy = ycmax;
1223 				}
1224 			}
1225 		}
1226 		else {
1227 			if (ycmax == ycmin) {
1228 				m_pDrw->cy = ycmin;
1229 			}
1230 			else {
1231 				dk4error_init(&er);
1232 				ycmin = i32_avg((m_pDrw->bb).yb, (m_pDrw->bb).yt, &er);
1233 				if (DK4_E_NONE == er.ec) {
1234 					m_pDrw->cy = ycmin;
1235 				}
1236 			}
1237 		}
1238 	}
1239 	else {
1240 	}
1241 
1242 }
1243 
1244 
1245 
1246 void
ZoomChanged(bool bZoomOut)1247 WxdkdrawFrame::ZoomChanged(bool bZoomOut)
1248 {
1249 	drawco->CalculateZoomFactor();
1250 	{
1251 		wxString s;
1252 		s.Printf("%g", drawco->m_dZoom);
1253 		lZoomPercent->SetLabel(s);
1254 	}
1255 	UpdateStipples();
1256 	UpdateFonts();
1257 	szTopBar->Layout();
1258 	lZoomPercent->Refresh();
1259 	if (bZoomOut && (0 != m_iv[IVI_C_COR_POSITION])) {
1260 		CorrectCenterPointIfNecessary();
1261 	}
1262 	drawco->CalculateConversionCoefficients();
1263 	AdjustScrollbars();
1264 	wxdobj_drw_require_redraw(m_pDrw, WXD_REFRESH_GRID);
1265 	drawco->Refresh();
1266 	m_bUpdate = true;
1267 }
1268 
1269 
1270 
1271 void
AdjustScrollbars(void)1272 WxdkdrawFrame::AdjustScrollbars(void)
1273 {
1274 	dk4_er_t	er;						/* Error report */
1275 	int			xPos;					/* Horizontal scrolblar position */
1276 	int			yPos;					/* Vertical scrollbar position */
1277 	int			xThumb;					/* Thumb size width (control width) */
1278 	int			yThumb;					/* Thumb size height (control height) */
1279 	int			xRange;					/* Range (required pixels) */
1280 	int			yRange;					/* Range (required pixels) */
1281 	int			xPageSize;				/* Pixels to scroll for page */
1282 	int			yPageSize;				/* Pixels to scroll for page */
1283 	bool		bEnableX	= false;	/* Enable horizontal scrollbar */
1284 	bool		bEnableY	= false;	/* Enable vertical scrollbar */
1285 
1286 	dk4error_init(&er);
1287 	xThumb = (drawco->m_szDrawco).GetWidth();
1288 	yThumb = (drawco->m_szDrawco).GetHeight();
1289 	xRange = dk4ma_int_from_double(
1290 		ceil(
1291 			(
1292 				(
1293 					(double)((m_pDrw->bb).xr) - (double)((m_pDrw->bb).xl)
1294 					+ (double)(m_pDrw->bleft) + (double)(m_pDrw->bright)
1295 				) * (drawco->m_ptRes).x * drawco->m_dZoom
1296 			) / RESWXD
1297 		), &er
1298 	);
1299 	yRange = dk4ma_int_from_double(
1300 		ceil(
1301 			(
1302 				(
1303 					(double)((m_pDrw->bb).yt) - (double)((m_pDrw->bb).yb)
1304 					+ (double)(m_pDrw->bbottom) + (double)(m_pDrw->btop)
1305 				) * (drawco->m_ptRes).y * drawco->m_dZoom
1306 			) / RESWXD
1307 		), &er
1308 	);
1309 	xPageSize = dk4ma_int_mul(xThumb, 4, &er) / 5;
1310 	yPageSize = dk4ma_int_mul(yThumb, 4, &er) / 5;
1311 	xPos = dk4ma_int_from_double(
1312 		dk4ma_rint(
1313 			(
1314 				(
1315 					(
1316 						(double)(m_pDrw->cx) - (double)((m_pDrw->bb).xl)
1317 						+ (double)(m_pDrw->bleft)
1318 					) * (drawco->m_ptRes).x * drawco->m_dZoom
1319 				) / RESWXD
1320 			) - ((double)xThumb / 2.0)
1321 		), &er
1322 	);
1323 	yPos = dk4ma_int_from_double(
1324 		dk4ma_rint(
1325 			(
1326 				(
1327 					(
1328 						(double)((m_pDrw->bb).yt) - (double)(m_pDrw->cy)
1329 						+ (double)(m_pDrw->btop)
1330 					) * (drawco->m_ptRes).y * drawco->m_dZoom
1331 				) / RESWXD
1332 			) - ((double)yThumb / 2.0)
1333 		), &er
1334 	);
1335 	if (0 > xPos) { xPos = 0; }
1336 	if (0 > yPos) { yPos = 0; }
1337 	if ((xRange - xThumb) < xPos) { xPos = xRange - xThumb; }
1338 	if ((yRange - yThumb) < yPos) { yPos = yRange - yThumb; }
1339 	if (DK4_E_NONE == er.ec) {
1340 		if (xRange > xThumb) {
1341 			bEnableX = true;
1342 		}
1343 		if (yRange > yThumb) {
1344 			bEnableY = true;
1345 		}
1346 	}
1347 	/*	Set up horizontal scrollbar
1348 	*/
1349 	if (bEnableX) {
1350 		if (!(sbHori->IsEnabled())) {
1351 			sbHori->Enable();
1352 		}
1353 
1354 
1355 
1356 
1357 		sbHori->SetScrollbar(xPos, xThumb, xRange, xPageSize, true);
1358 		sbHori->SetThumbPosition(xPos);
1359 		sbHori->Refresh();
1360 	}
1361 	else {
1362 		if (sbHori->IsEnabled()) {
1363 			sbHori->Enable(false);
1364 			sbHori->Refresh();
1365 		}
1366 	}
1367 	/*	Set up vertical scrollbar
1368 	*/
1369 	if (bEnableY) {
1370 		if (!(sbVert->IsEnabled())) {
1371 			sbVert->Enable();
1372 		}
1373 
1374 
1375 
1376 
1377 		sbVert->SetScrollbar(yPos, yThumb, yRange, yPageSize, true);
1378 		sbVert->SetThumbPosition(yPos);
1379 		sbVert->Refresh();
1380 	}
1381 	else {
1382 		if (sbVert->IsEnabled()) {
1383 			sbVert->Enable(false);
1384 			sbVert->Refresh();
1385 		}
1386 	}
1387 }
1388 
1389 
1390 
1391 void
StartEventHandling(void)1392 WxdkdrawFrame::StartEventHandling(void)
1393 {
1394 	dk4error_init(&m_oErrorReport);
1395 	m_bUpdate = false;
1396 }
1397 
1398 
1399 
1400 void
MoveScrollbar(wxScrollBar * sb,int lines,bool vert)1401 WxdkdrawFrame::MoveScrollbar(wxScrollBar *sb, int lines, bool vert)
1402 {
1403 	int		range;					/* Scrollbar range (maximum) */
1404 #if	0
1405 	int		ps;						/* Page size */
1406 #endif
1407 	int		pos;					/* Position */
1408 	int		ts;						/* Thumb size */
1409 
1410 	range = sb->GetRange();
1411 #if	0
1412 	ps    = sb->GetPageSize();
1413 #endif
1414 	pos   = sb->GetThumbPosition();
1415 	ts    = sb->GetThumbSize();
1416 
1417 	if (range > ts) {
1418 		pos -= (lines * ts) / 10;
1419 		if (0 > pos) { pos = 0; }
1420 		if ((range - ts) <= pos) { pos = range - ts - 1; }
1421 		sb->SetThumbPosition(pos);
1422 		if (vert) {
1423 			UseScrollV();
1424 		}
1425 		else {
1426 			UseScrollH();
1427 		}
1428 		sb->Refresh();
1429 		sb->Update();
1430 	}
1431 
1432 }
1433 
1434 
1435 
1436 void
ControlMouseWheel(wxMouseEvent & event)1437 WxdkdrawFrame::ControlMouseWheel(wxMouseEvent & event)
1438 {
1439 	int		modifiers;		/* Modifier keys */
1440 	int		rotation;		/* Rotation of wheel */
1441 	int		delta;			/* Required rotation for line */
1442 	int		lines;			/* Number of lines */
1443 	int8_t	ozl;
1444 
1445 	StartEventHandling();
1446 	if (UpdateMousePosition(event)) {
1447 		wxdobj_drw_require_redraw(m_pDrw, WXD_REFRESH_MARKUP);
1448 	}
1449 	modifiers = event.GetModifiers();
1450 	rotation  = event.GetWheelRotation();
1451 	delta     = event.GetWheelDelta();
1452 	switch (modifiers) {
1453 		case wxMOD_CONTROL : {
1454 			m_iWheelControl += rotation;
1455 			lines = m_iWheelControl / delta;
1456 			m_iWheelControl -= (lines * delta);
1457 			ozl = m_pDrw->zl;
1458 			if (0 < lines) {
1459 				while (0 < lines--) {
1460 					if ((int8_t)(-14) < m_pDrw->zl) {
1461 						m_pDrw->zl = (int8_t)(m_pDrw->zl - 1);
1462 					}
1463 				}
1464 			}
1465 			else {
1466 				if (0 > lines) {
1467 					while (0 > lines++) {
1468 						if ((int8_t)14 > m_pDrw->zl) {
1469 							m_pDrw->zl = (int8_t)(m_pDrw->zl + 1);
1470 						}
1471 					}
1472 				}
1473 			}
1474 			if (ozl != m_pDrw->zl) {
1475 				ZoomChanged((ozl > m_pDrw->zl));
1476 				UpdateGridPosition();
1477 			}
1478 		} break;
1479 		case wxMOD_SHIFT : {
1480 			m_iWheelShift   += rotation;
1481 			lines = m_iWheelShift /delta;
1482 			m_iWheelShift   -= (lines * delta);
1483 			if (sbHori->IsEnabled()) {
1484 				MoveScrollbar(sbHori, lines, false);
1485 				drawco->CalculateConversionCoefficients();
1486 				UpdateGridPosition();
1487 				wxdobj_drw_require_redraw(m_pDrw, WXD_REFRESH_GRID);
1488 			}
1489 		} break;
1490 		case wxMOD_NONE : {
1491 			m_iWheelNormal  += rotation;
1492 			lines = m_iWheelNormal / delta;
1493 			m_iWheelNormal  -= (lines * delta);
1494 			if (sbVert->IsEnabled()) {
1495 				MoveScrollbar(sbVert, lines, true);
1496 				drawco->CalculateConversionCoefficients();
1497 				UpdateGridPosition();
1498 				wxdobj_drw_require_redraw(m_pDrw, WXD_REFRESH_GRID);
1499 			}
1500 		} break;
1501 	}
1502 
1503 	EndEventHandling();
1504 }
1505 
1506 
1507 
1508 void
UseScrollH(void)1509 WxdkdrawFrame::UseScrollH(void)
1510 {
1511 	dk4_er_t	er;			/* Error report */
1512 	int32_t		cx;			/* Center x */
1513 	int			tp;			/* Thumb position */
1514 	int			ts;			/* Thumb size */
1515 #if	0
1516 	int			r;
1517 	int			p;
1518 #endif
1519 
1520 #if	0
1521 	r  = sbHori->GetRange();
1522 	p  = sbHori->GetPageSize();
1523 #endif
1524 	tp = sbHori->GetThumbPosition();
1525 	ts = sbHori->GetThumbSize();
1526 	dk4error_init(&er);
1527 	cx = dk4ma_int32_from_double(
1528 		dk4ma_rint(
1529 			(
1530 				((double)tp + (double)ts / 2.0) * RESWXD
1531 			)	/ ((drawco->m_ptRes).x * drawco->m_dZoom)
1532 		), &er
1533 	);
1534 	cx = dk4ma_int32_t_add(cx, (m_pDrw->bb).xl, &er);
1535 	cx = dk4ma_int32_t_sub(cx, m_pDrw->bleft, &er);
1536 	if (DK4_E_NONE == er.ec) {
1537 		m_pDrw->cx = cx;
1538 		wxdobj_drw_require_redraw(m_pDrw, WXD_REFRESH_GRID);
1539 		drawco->Refresh();
1540 		m_bUpdate = true;
1541 	}
1542 
1543 }
1544 
1545 
1546 
1547 void
UseScrollV(void)1548 WxdkdrawFrame::UseScrollV(void)
1549 {
1550 	dk4_er_t	er;		/* Error report */
1551 	int32_t		cy;		/* Center y */
1552 	int			tp;		/* Thumb position */
1553 	int			ts;		/* Thumb size */
1554 #if	0
1555 	int			r;
1556 	int			p;
1557 #endif
1558 
1559 #if	0
1560 	r  = sbVert->GetRange();
1561 	p  = sbVert->GetPageSize();
1562 #endif
1563 	tp = sbVert->GetThumbPosition();
1564 	ts = sbVert->GetThumbSize();
1565 	dk4error_init(&er);
1566 	cy = dk4ma_int32_from_double(
1567 		dk4ma_rint(
1568 			(
1569 				((double)tp + (double)ts / 2.0) * RESWXD
1570 			)	/ ((drawco->m_ptRes).x * drawco->m_dZoom)
1571 		), &er
1572 	);
1573 	cy = dk4ma_int32_t_sub((m_pDrw->bb).yt, cy, &er);
1574 	cy = dk4ma_int32_t_add(cy, m_pDrw->btop, &er);
1575 	if (DK4_E_NONE == er.ec) {
1576 		m_pDrw->cy = cy;
1577 		wxdobj_drw_require_redraw(m_pDrw, WXD_REFRESH_GRID);
1578 		drawco->Refresh();
1579 		m_bUpdate = true;
1580 	}
1581 
1582 }
1583 
1584 
1585 
1586 #if 0
1587 
1588 static
1589 bool
1590 ColourChooserDiffersFromColour(Dk4WxColourView *pcc, int *pcol)
1591 {
1592 	bool		back = false;
1593 	if (pcc->Red() != pcol[0]) {
1594 		back = true;
1595 	}
1596 	else {
1597 		if (pcc->Green() != pcol[1]) {
1598 			back = true;
1599 		}
1600 		else {
1601 			if (pcc->Blue() != pcol[2]) {
1602 				back = true;
1603 			}
1604 		}
1605 	}
1606 	return back;
1607 }
1608 
1609 #endif
1610 
1611 
1612 
1613 void
StyleToGUI(bool refresh)1614 WxdkdrawFrame::StyleToGUI(bool refresh)
1615 {
1616 	int		valrotation		= 0;		/* Rotation value */
1617 	bool	enalayer		= true;		/* Enable layer spin control */
1618 	bool	enalinecolour	= false;	/* Enable line colour chooser */
1619 	bool	enalinewidth	= false;	/* Enable line width spin control */
1620 	bool	enalinestyle	= false;	/* Enable line style button */
1621 	bool	enajoinstyle	= false;	/* Enable join style button */
1622 	bool	enacapstyle		= false;	/* Enable cap style button */
1623 	bool	enafwarrow		= false;	/* Enable forward arrow button */
1624 	bool	enabwarrow		= false;	/* Enable backward arrow button */
1625 	bool	enafillcolour	= false;	/* Enable fill colour chooser */
1626 	bool	enafillstyle	= false;	/* Enable fill style button */
1627 	bool	enalatex		= false;	/* Enable LaTeX checkbox */
1628 	bool	enatextalign	= false;	/* Enable text align button */
1629 	bool	enatextfont		= false;	/* Enable text font button */
1630 	bool	enatextsize		= false;	/* Enable text size spin control */
1631 	bool	enarotation		= false;	/* Enable rotation spin control */
1632 
1633 	if (NULL != m_pStyle) {
1634 		/*
1635 			Check which style elements to enable
1636 		*/
1637 		switch ( (int)(m_pStyle->ot) ) {
1638 			case WXD_OT_TEXT : {
1639 				enalinecolour	= true;
1640 				enalatex		= true;
1641 				enatextalign	= true;
1642 				enatextfont		= true;
1643 				enatextsize		= true;
1644 				enarotation		= true;
1645 				valrotation		= (m_pStyle->det).t.a;
1646 			} break;
1647 			case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : {
1648 				enalinecolour	= true;
1649 				enalinewidth	= true;
1650 				enalinestyle	= true;
1651 				enajoinstyle	= true;
1652 				enacapstyle		= true;
1653 				enafwarrow		= true;
1654 				enabwarrow		= true;
1655 			} break;
1656 			case WXD_OT_O_ARC : {
1657 				enalinecolour	= true;
1658 				enalinewidth	= true;
1659 				enalinestyle	= true;
1660 				enacapstyle		= true;
1661 				enafwarrow		= true;
1662 				enabwarrow		= true;
1663 			} break;
1664 			case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : {
1665 
1666 				enalinecolour	= true;
1667 				enalinewidth	= true;
1668 				enalinestyle	= true;
1669 				enajoinstyle	= true;
1670 				enafillcolour	= true;
1671 				enafillstyle	= true;
1672 			} break;
1673 			case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : {
1674 				enalinecolour	= true;
1675 				enalinewidth	= true;
1676 				enalinestyle	= true;
1677 				enafillcolour	= true;
1678 				enafillstyle	= true;
1679 				if (WXD_OT_ELLIPSE == m_pStyle->ot) {
1680 					enarotation	= true;
1681 					valrotation = (m_pStyle->det).e.a;
1682 				}
1683 			} break;
1684 			case WXD_OT_BOX : {
1685 				enalinecolour	= true;
1686 				enalinewidth	= true;
1687 				enalinestyle	= true;
1688 				enajoinstyle	= true;
1689 				enafillcolour	= true;
1690 				enafillstyle	= true;
1691 			} break;
1692 			case WXD_OT_IMAGE : {
1693 				enafillcolour	= true;
1694 			} break;
1695 			case WXD_OT_DOT_FILLED : {
1696 				enalinecolour	= true;
1697 			} break;
1698 			case WXD_OT_DOT_WHITE : {
1699 				enalinecolour	= true;
1700 				enalinewidth	= true;
1701 			} break;
1702 			default : {
1703 			} break;
1704 		}
1705 
1706 		/*
1707 			Prepare to change style for selected object.
1708 		*/
1709 
1710 		/* Layer */
1711 		spLayerNumber->SetValue( (int)(m_pStyle->lay) );
1712 		spLayerNumber->Enable(enalayer);
1713 		if (refresh) { spLayerNumber->Refresh(); m_bUpdate = true; }
1714 
1715 
1716 		/* Line colour */
1717 		ccLineColour->SetRGB(m_pStyle->sc[0], m_pStyle->sc[1], m_pStyle->sc[2]);
1718 
1719 		ccLineColour->Enable(enalinecolour);
1720 		if (refresh) { ccLineColour->Refresh(); m_bUpdate =  true; }
1721 
1722 
1723 		/* Line width */
1724 		spLineWidth->SetValue( (int)(m_pStyle->lw) );
1725 
1726 		spLineWidth->Enable(enalinewidth);
1727 		if (refresh) { spLineWidth->Refresh(); m_bUpdate = true; }
1728 
1729 
1730 		/* Line style */
1731 		bStyleLineStyle->SetBitmap(WxdkdrawFrame::ms_ls_images[m_pStyle->ls]);
1732 
1733 		bStyleLineStyle->Enable(enalinestyle);
1734 		if (refresh) { bStyleLineStyle->Refresh(); m_bUpdate = true; }
1735 
1736 
1737 		/* Join style */
1738 		bStyleLineJoins->SetBitmap(WxdkdrawFrame::ms_lj_images[m_pStyle->js]);
1739 		bStyleLineJoins->Enable(enajoinstyle);
1740 		if (refresh) { bStyleLineJoins->Refresh(); m_bUpdate = true; }
1741 
1742 
1743 		/* Cap style */
1744 		bStyleLineEnds->SetBitmap(WxdkdrawFrame::ms_lc_images[m_pStyle->cs]);
1745 		bStyleLineEnds->Enable(enacapstyle);
1746 		if (refresh) { bStyleLineEnds->Refresh(); m_bUpdate = true; }
1747 
1748 
1749 		/* Forward arrow */
1750 		bStyleArrowForward->SetBitmap(
1751 			WxdkdrawFrame::ms_arrow_images[m_pStyle->aft]
1752 		);
1753 		bStyleArrowForward->Enable(enafwarrow);
1754 		if (refresh) { bStyleArrowForward->Refresh(); m_bUpdate = true; }
1755 
1756 
1757 		/* Backward arrow */
1758 		bStyleArrowBackward->SetBitmap(
1759 			WxdkdrawFrame::ms_arrow_images[m_pStyle->abt]
1760 		);
1761 		bStyleArrowBackward->Enable(enabwarrow);
1762 		if (refresh) { bStyleArrowBackward->Refresh(); m_bUpdate = true; }
1763 
1764 
1765 		/* Fill colour */
1766 		ccFillColour->SetRGB(
1767 			m_pStyle->fc[0], m_pStyle->fc[1], m_pStyle->fc[2]
1768 		);
1769 		ccFillColour->Enable(enafillcolour);
1770 		if (refresh) { ccFillColour->Refresh(); m_bUpdate = true; }
1771 
1772 
1773 		/* Fill style */
1774 		bStyleFillPattern->SetBitmap(WxdkdrawFrame::ms_fs_images[m_pStyle->fs]);
1775 		bStyleFillPattern->Enable(enafillstyle);
1776 		if (refresh) { bStyleFillPattern->Refresh(); m_bUpdate = true; }
1777 
1778 
1779 		if (WXD_OT_TEXT == m_pStyle->ot) {
1780 
1781 			/* LaTeX text flag */
1782 			cbStyleTextLaTeX->SetValue(
1783 				WXD_TEXT_FLAG_NONE
1784 				!= (WXD_TEXT_FLAG_LATEX & (m_pStyle->det).t.fl)
1785 			);
1786 			cbStyleTextLaTeX->Enable(enalatex);
1787 			if (refresh) { cbStyleTextLaTeX->Refresh(); m_bUpdate = true; }
1788 
1789 
1790 
1791 			bStyleTextAlign->SetBitmap(
1792 				WxdkdrawFrame::ms_ta_images[(m_pStyle->det).t.al]
1793 			);
1794 			bStyleTextAlign->Enable(enatextalign);
1795 			if (refresh) { bStyleTextAlign->Refresh(); m_bUpdate = true; }
1796 
1797 
1798 			/* Text font */
1799 			bStyleFontName->SetBitmap(
1800 				WxdkdrawFrame::ms_fn_images[(m_pStyle->det).t.find]
1801 			);
1802 			bStyleFontName->Enable(enatextfont);
1803 			if (refresh) { bStyleFontName->Refresh(); m_bUpdate = true; }
1804 
1805 
1806 			/* Text size */
1807 			spFontSize->SetValue((m_pStyle->det).t.fsz);
1808 			spFontSize->Enable(enatextsize);
1809 			if (refresh) { spFontSize->Refresh(); m_bUpdate = true; }
1810 
1811 
1812 		}
1813 		else {
1814 			cbStyleTextLaTeX->Enable(false);
1815 			bStyleTextAlign->Enable(false);
1816 			bStyleFontName->Enable(false);
1817 			spFontSize->Enable(false);
1818 		}
1819 		spRotation->SetValue(valrotation);
1820 		spRotation->Enable(enarotation);
1821 		if (refresh) { spRotation->Refresh(); m_bUpdate = true; }
1822 	}
1823 	else {
1824 		/*
1825 			Prepare to change default styles.
1826 		*/
1827 
1828 		/* Layer number */
1829 		spLayerNumber->SetValue( (int)(m_oStyle.lay) );
1830 		spLayerNumber->Enable();
1831 		if (refresh) { spLayerNumber->Refresh(); m_bUpdate =  true; }
1832 
1833 		/* Line colour */
1834 		ccLineColour->SetRGB( m_oStyle.sc[0], m_oStyle.sc[1], m_oStyle.sc[2] );
1835 		ccLineColour->Enable();
1836 		if (refresh) { ccLineColour->Refresh(); m_bUpdate = true; }
1837 
1838 		/* Line width */
1839 		spLineWidth->SetValue( (int)(m_oStyle.lw) );
1840 		spLineWidth->Enable();
1841 		if (refresh) { spLineWidth->Refresh(); m_bUpdate = true; }
1842 
1843 		/* Line style */
1844 		bStyleLineStyle->SetBitmap(WxdkdrawFrame::ms_ls_images[m_oStyle.ls]);
1845 		bStyleLineStyle->Enable();
1846 		if (refresh) { bStyleLineStyle->Refresh(); m_bUpdate = true; }
1847 
1848 		/* Join style */
1849 		bStyleLineJoins->SetBitmap(WxdkdrawFrame::ms_lj_images[m_oStyle.js]);
1850 		bStyleLineJoins->Enable();
1851 		if (refresh) { bStyleLineJoins->Refresh(); m_bUpdate = true; }
1852 
1853 		/* Cap style */
1854 		bStyleLineEnds->SetBitmap(WxdkdrawFrame::ms_lc_images[m_oStyle.cs]);
1855 		bStyleLineEnds->Enable();
1856 		if (refresh) { bStyleLineEnds->Refresh(); m_bUpdate = true; }
1857 
1858 		/* Forward arrow */
1859 		bStyleArrowForward->SetBitmap(
1860 			WxdkdrawFrame::ms_arrow_images[m_oStyle.aft]
1861 		);
1862 		bStyleArrowForward->Enable();
1863 		if (refresh) { bStyleArrowForward->Refresh(); m_bUpdate = true; }
1864 
1865 		/* Backward arrow */
1866 		bStyleArrowBackward->SetBitmap(
1867 			WxdkdrawFrame::ms_arrow_images[m_oStyle.abt]
1868 		);
1869 		bStyleArrowBackward->Enable();
1870 		if (refresh) { bStyleArrowBackward->Refresh(); m_bUpdate = true; }
1871 
1872 		/* Fill colour */
1873 		ccFillColour->SetRGB( m_oStyle.fc[0], m_oStyle.fc[1], m_oStyle.fc[2] );
1874 		ccFillColour->Enable();
1875 		if (refresh) { ccFillColour->Refresh(); m_bUpdate = true; }
1876 
1877 		/* Fill style */
1878 		bStyleFillPattern->SetBitmap(WxdkdrawFrame::ms_fs_images[m_oStyle.fs]);
1879 		bStyleFillPattern->Enable();
1880 		if (refresh) { bStyleFillPattern->Refresh(); m_bUpdate = true; }
1881 
1882 		/* LaTeX text flag */
1883 		cbStyleTextLaTeX->SetValue(
1884 			WXD_TEXT_FLAG_NONE != (WXD_TEXT_FLAG_LATEX & m_oStyle.det.t.fl)
1885 		);
1886 		cbStyleTextLaTeX->Enable();
1887 		if (refresh) { cbStyleTextLaTeX->Refresh(); m_bUpdate = true; }
1888 
1889 		/* Text align */
1890 		bStyleTextAlign->SetBitmap(
1891 			WxdkdrawFrame::ms_ta_images[m_oStyle.det.t.al]
1892 		);
1893 		bStyleTextAlign->Enable();
1894 		if (refresh) { bStyleTextAlign->Refresh(); m_bUpdate = true; }
1895 
1896 		/* Text font */
1897 		bStyleFontName->SetBitmap(
1898 			WxdkdrawFrame::ms_fn_images[m_oStyle.det.t.find]
1899 		);
1900 		bStyleFontName->Enable();
1901 		if (refresh) { bStyleFontName->Refresh(); m_bUpdate = true; }
1902 
1903 		/* Text size */
1904 		spFontSize->SetValue(m_oStyle.det.t.fsz);
1905 		spFontSize->Enable();
1906 		if (refresh) { spFontSize->Refresh(); m_bUpdate = true; }
1907 
1908 		/* Rotation */
1909 		spRotation->SetValue(0);
1910 		spRotation->Enable(false);
1911 		if (refresh) { spRotation->Refresh(); m_bUpdate = true; }
1912 	}
1913 
1914 }
1915 
1916 
1917 
1918 void
SetStyleObject(Wxd_object_t * pObj,bool bUpdate)1919 WxdkdrawFrame::SetStyleObject(Wxd_object_t *pObj, bool bUpdate)
1920 {
1921 	if (m_pStyle != pObj) {
1922 		m_pStyle = pObj;
1923 		StyleToGUI(bUpdate);
1924 	}
1925 }
1926 
1927 
1928 
1929 void
UpdateOneFont(Wxd_font_t * pfont)1930 WxdkdrawFrame::UpdateOneFont(
1931 	Wxd_font_t		*pfont
1932 )
1933 {
1934 	pfont->attempted = false;
1935 	if (NULL != pfont->font) {
1936 		delete (pfont->font);
1937 		pfont->font = NULL;
1938 	}
1939 	wxdfont_find_font(
1940 		pfont, drawco->m_dZoom, (drawco->m_ptRes).y,
1941 		(0 != m_iv[IVI_FONT_EXACT])
1942 	);
1943 }
1944 
1945 
1946 
1947 void
UpdateFonts(void)1948 WxdkdrawFrame::UpdateFonts(void)
1949 {
1950 	Wxd_font_t		*pfont;
1951 	Wxd_object_t	*pobj;
1952 
1953 	/*	Connect text details to fonts.
1954 	*/
1955 
1956 	dk4sto_it_reset(m_pDrw->i_flat);
1957 	do {
1958 		pobj = (Wxd_object_t *)dk4sto_it_next(m_pDrw->i_flat);
1959 		if (NULL != pobj) {
1960 			if (WXD_OT_TEXT == pobj->ot) {
1961 				if (NULL == (pobj->det).t.font) {
1962 					(pobj->det).t.font = FindFont(
1963 						(pobj->det).t.find, (pobj->det).t.fsz
1964 					);
1965 				}
1966 			}
1967 		}
1968 	} while (NULL != pobj);
1969 
1970 	/*	Clear and renew all fonts
1971 	*/
1972 
1973 	dk4sto_it_reset(m_pDrw->i_fonts);
1974 	do {
1975 		pfont = (Wxd_font_t *)dk4sto_it_next(m_pDrw->i_fonts);
1976 		if (NULL != pfont) {
1977 			UpdateOneFont(pfont);
1978 		}
1979 	} while (NULL != pfont);
1980 
1981 
1982 }
1983 
1984 
1985 
1986 Wxd_font_t *
FindFont(uint8_t find,uint16_t fsz)1987 WxdkdrawFrame::FindFont(uint8_t find, uint16_t fsz)
1988 {
1989 	Wxd_font_t		 tf;
1990 	Wxd_font_t		*back	= NULL;
1991 
1992 	tf.find = find; tf.fsz = fsz;
1993 	back = (Wxd_font_t *)dk4sto_it_find_like(m_pDrw->i_fonts, &tf, 0);
1994 	if (NULL == back) {
1995 		back = wxdfont_new(find, fsz);
1996 		if (NULL != back) {
1997 			if (0 != dk4sto_add(m_pDrw->s_fonts, back, NULL)) {
1998 				wxdfont_find_font(
1999 					back, drawco->m_dZoom, (drawco->m_ptRes).y,
2000 					(0 != m_iv[IVI_FONT_EXACT])
2001 				);
2002 			}
2003 			else {
2004 				wxdfont_delete(back);
2005 				back = NULL;
2006 			}
2007 		}
2008 	}
2009 	return back;
2010 }
2011 
2012 
2013 
2014 bool
ObjectSelectableInState(Wxd_object_t const * pobj)2015 WxdkdrawFrame::ObjectSelectableInState(Wxd_object_t const *pobj)
2016 {
2017 	bool		back	= false;
2018 	if (NULL != pobj) {
2019 		back = true;
2020 		/*
2021 			_STATE_
2022 			In some states we want to select objects of certain
2023 			types only
2024 		*/
2025 		switch (m_iState) {
2026 			case S_MOD_SPLINE : {
2027 				back = false;
2028 				switch ( (int)(pobj->ot) ) {
2029 					case WXD_OT_O_SPLINE :
2030 					case WXD_OT_C_SPLINE :
2031 					{
2032 						back = true;
2033 					} break;
2034 				}
2035 			} break;
2036 			case S_ROTATE : {
2037 				switch ( (int)(pobj->ot) ) {
2038 					case WXD_OT_CIRCLE :
2039 					case WXD_OT_DOT_FILLED :
2040 					case WXD_OT_DOT_WHITE :
2041 					{
2042 						if (NULL == pobj->pa) {
2043 							back = false;
2044 						}
2045 					} break;
2046 				}
2047 			} break;
2048 			case S_CONVERT : {
2049 				back = wxdobj_can_convert(m_iObjToCreate, pobj);
2050 			} break;
2051 			case S_FLIP : {
2052 				/*
2053 					For some object types flipping would result
2054 					in no change
2055 				*/
2056 				switch ( (int)(pobj->ot) ) {
2057 					case WXD_OT_CIRCLE :
2058 					case WXD_OT_BOX :
2059 					case WXD_OT_IMAGE :
2060 					case WXD_OT_DOT_FILLED :
2061 					case WXD_OT_DOT_WHITE : {
2062 						if (NULL == pobj->pa) {
2063 							back = false;
2064 						}
2065 					} break;
2066 				}
2067 			} break;
2068 			case S_UNGROUP : {
2069 				/*
2070 					Only members of groups are of interest, from the member
2071 					we go upwards to find the top level group object
2072 				*/
2073 				if (NULL == pobj->pa) {
2074 					back = false;
2075 				}
2076 			} break;
2077 			case S_DETAILS : {
2078 				/*
2079 					The details to modify - if any - depend on the object type:
2080 				*/
2081 				switch ( (int)(pobj->ot) ) {
2082 					case WXD_OT_TEXT :			/* Texts */
2083 					case WXD_OT_BOX :			/* Rounded corner radius */
2084 					case WXD_OT_IMAGE :			/* Image file and flags */
2085 					case WXD_OT_DOT_FILLED :	/* Diameter */
2086 					case WXD_OT_DOT_WHITE :		/* Diameter */
2087 					{
2088 						back = true;
2089 					} break;
2090 					default : {
2091 						back = false;
2092 					} break;
2093 				}
2094 			} break;
2095 		}
2096 	}
2097 	return back;
2098 }
2099 
2100 
2101 
2102 Wxd_object_t *
FindNearestObject(bool gr)2103 WxdkdrawFrame::FindNearestObject(bool gr)
2104 {
2105 	Wxd_object_t	*back	= NULL;		/* Object with minimum distance */
2106 	Wxd_object_t	*pobj;				/* Current object */
2107 	double			 min	= -1.0;		/* Minimum distance found so far */
2108 	double			 d;					/* Distance to current object */
2109 
2110 	dk4sto_it_reset(m_pDrw->i_flat);
2111 	do {
2112 		pobj = (Wxd_object_t *)dk4sto_it_next(m_pDrw->i_flat);
2113 		if (NULL != pobj) {
2114 			if ((wxdobj_is_active(pobj)) && (ObjectSelectableInState(pobj))) {
2115 				d = wxdobj_distance_to_point(pobj, &m_ptMousePosRaw);
2116 				if (
2117 					(0.0 < d)
2118 					&& ((0.0 > min) || (d < min))
2119 					&& (d < 2.0 * (double)(drawco->m_uGridSnap))
2120 				) {
2121 					min = d;
2122 					back = pobj;
2123 				}
2124 			}
2125 		}
2126 	} while (NULL != pobj);
2127 	if ((gr) && (NULL != back)) {
2128 		while (NULL != back->pa) { back = back->pa; }
2129 	}
2130 	return back;
2131 }
2132 
2133 
2134 
2135 void
RequireRedraw(int level)2136 WxdkdrawFrame::RequireRedraw(int level)
2137 {
2138 	wxdobj_drw_require_redraw(m_pDrw, level);
2139 	drawco->Refresh();
2140 	Update();
2141 }
2142 
2143 
2144 
2145 void
UpdateTextForFont(Wxd_object_t * pobj,bool bRedraw)2146 WxdkdrawFrame::UpdateTextForFont(Wxd_object_t *pobj, bool bRedraw)
2147 {
2148 	Wxd_font_t	*pfont;
2149 	bool		 hasf;
2150 
2151 	hasf = (NULL != (pobj->det).t.font);
2152 	(pobj->det).t.font = pfont = FindFont((pobj->det).t.find,(pobj->det).t.fsz);
2153 	if (NULL != pfont) {
2154 		UpdateOneFont(pfont);
2155 	}
2156 	if (hasf) {
2157 		wxdobj_remove_unused_fonts(m_pDrw);
2158 	}
2159 	if (bRedraw) {
2160 		RequireRedraw(WXD_REFRESH_DRAWING);
2161 	}
2162 
2163 }
2164 
2165 
2166 
2167 void
SetMouseAndStatusTexts(int st)2168 WxdkdrawFrame::SetMouseAndStatusTexts(int st)
2169 {
2170 
2171 	/*	Defaults
2172 	*/
2173 
2174 	msgMouseL->SetLabel(sNlWx[7]);
2175 	msgMouseM->SetLabel(sNlWx[7]);
2176 	msgMouseR->SetLabel(sNlWx[7]);
2177 	SetStatusText(sNlWx[7]);
2178 	/*
2179 		_STATE_	Messages depending on state to enter.
2180 	*/
2181 	switch (st) {
2182 		case S_NOOP : {
2183 		} break;
2184 		case S_DELETE : {
2185 			msgMouseR->SetLabel(sTexts[341]);
2186 			msgMouseM->SetLabel(sTexts[534]);
2187 		} break;
2188 		case S_REGION_DELETE : {
2189 			msgMouseL->SetLabel(sTexts[532]);
2190 			msgMouseR->SetLabel(sTexts[533]);
2191 		} break;
2192 		case S_MOVE_SELECT : {
2193 			msgMouseL->SetLabel(sNlWx[7]);
2194 			msgMouseR->SetLabel(sTexts[344]);
2195 		} break;
2196 		case S_MOVE_PLACE : {
2197 		} break;
2198 		case S_COPY_SELECT : {
2199 			msgMouseL->SetLabel(sNlWx[7]);
2200 			msgMouseR->SetLabel(sTexts[372]);
2201 		} break;
2202 		case S_COPY_PLACE : {
2203 		} break;
2204 		case S_POLY_FIRST : {
2205 			msgMouseL->SetLabel(sTexts[373]);
2206 			msgMouseR->SetLabel(sTexts[375]);
2207 			SetStatusText(
2208 				sTexts[(WXD_OT_POLYLINE == m_iObjToCreate) ? 30 : 32]
2209 			);
2210 		} break;
2211 		case S_POLY_FURTHER : {
2212 			msgMouseL->SetLabel(
2213 				(IsAcceptablePoint()) ? (sTexts[374]) : (sNlWx[7])
2214 			);
2215 			msgMouseR->SetLabel(sTexts[376]);
2216 			SetStatusText(
2217 				sTexts[(WXD_OT_POLYLINE == m_iObjToCreate) ? 30 : 32]
2218 			);
2219 		} break;
2220 		case S_SPLINE_FIRST : {
2221 			msgMouseL->SetLabel(sTexts[373]);
2222 			msgMouseR->SetLabel(sTexts[375]);
2223 			if (WXD_OT_C_SPLINE == m_iObjToCreate) {
2224 				SetStatusText(sTexts[m_bSplineInterpolated ? 48 : 44]);
2225 			}
2226 			else {
2227 				SetStatusText(sTexts[m_bSplineInterpolated ? 46 : 42]);
2228 			}
2229 		} break;
2230 		case S_SPLINE_FURTHER : {
2231 			msgMouseL->SetLabel(
2232 				(IsAcceptablePoint()) ? (sTexts[374]) : (sNlWx[7])
2233 			);
2234 			msgMouseR->SetLabel(sTexts[376]);
2235 			if (WXD_OT_C_SPLINE == m_iObjToCreate) {
2236 				SetStatusText(sTexts[m_bSplineInterpolated ? 48 : 44]);
2237 			}
2238 			else {
2239 				SetStatusText(sTexts[m_bSplineInterpolated ? 46 : 42]);
2240 			}
2241 		} break;
2242 		case S_BOX_FIRST : {
2243 			msgMouseL->SetLabel(sTexts[377]);
2244 			msgMouseR->SetLabel(sTexts[379]);
2245 			SetStatusText(sTexts[m_bSplineInterpolated ? 36 : 34]);
2246 		} break;
2247 		case S_BOX_OPPOSITE : {
2248 			msgMouseL->SetLabel(
2249 				(IsAcceptablePoint()) ? (sTexts[378]) : (sNlWx[7])
2250 			);
2251 			msgMouseR->SetLabel(sTexts[379]);
2252 			SetStatusText(sTexts[m_bSplineInterpolated ? 36 : 34]);
2253 		} break;
2254 		case S_CIRCLE_CENTER : {
2255 			msgMouseL->SetLabel(sTexts[380]);
2256 			msgMouseR->SetLabel(sTexts[383]);
2257 			SetStatusText(sTexts[38]);
2258 		} break;
2259 		case S_CIRCLE_RADIUS : {
2260 			msgMouseL->SetLabel(
2261 				(IsAcceptablePoint()) ? (sTexts[381]) : (sNlWx[7])
2262 			);
2263 			msgMouseR->SetLabel(sTexts[382]);
2264 			SetStatusText(sTexts[38]);
2265 		} break;
2266 		case S_ELLIPSE_CENTER : {
2267 			msgMouseL->SetLabel(sTexts[380]);
2268 			msgMouseR->SetLabel(sTexts[383]);
2269 			SetStatusText(sTexts[40]);
2270 		} break;
2271 		case S_ELLIPSE_CORNER : {
2272 			msgMouseL->SetLabel(
2273 				(IsAcceptablePoint()) ? (sTexts[384]) : (sNlWx[7])
2274 			);
2275 			msgMouseR->SetLabel(sTexts[382]);
2276 			SetStatusText(sTexts[40]);
2277 		} break;
2278 		case S_ARC_1 : {
2279 			msgMouseL->SetLabel(sTexts[389]);
2280 			msgMouseR->SetLabel(sTexts[393]);
2281 			SetStatusText(sTexts[(WXD_OT_C_ARC == m_iObjToCreate) ? 388 : 386]);
2282 		} break;
2283 		case S_ARC_2 : {
2284 			msgMouseL->SetLabel(
2285 				(IsAcceptablePoint()) ? (sTexts[390]) : (sNlWx[7])
2286 			);
2287 			msgMouseR->SetLabel(sTexts[392]);
2288 			SetStatusText(sTexts[(WXD_OT_C_ARC == m_iObjToCreate) ? 388 : 386]);
2289 		} break;
2290 		case S_ARC_3 : {
2291 			msgMouseL->SetLabel(
2292 				(IsAcceptablePoint()) ? (sTexts[391]) : (sNlWx[7])
2293 			);
2294 			msgMouseR->SetLabel(sTexts[392]);
2295 			SetStatusText(sTexts[(WXD_OT_C_ARC == m_iObjToCreate) ? 388 : 386]);
2296 		} break;
2297 		case S_DOT : {
2298 			msgMouseL->SetLabel(sTexts[394]);
2299 			msgMouseR->SetLabel(sTexts[395]);
2300 			SetStatusText(
2301 				sTexts[(WXD_OT_DOT_WHITE == m_iObjToCreate) ? 52 : 50]
2302 			);
2303 		} break;
2304 		case S_TEXT : {
2305 			msgMouseL->SetLabel(sTexts[403]);
2306 			msgMouseR->SetLabel(sTexts[404]);
2307 			SetStatusText(sTexts[54]);
2308 		} break;
2309 		case S_IMG_1 : {
2310 			msgMouseL->SetLabel(sTexts[405]);
2311 			msgMouseR->SetLabel(sTexts[408]);
2312 			SetStatusText(sTexts[56]);
2313 		} break;
2314 		case S_IMG_2 : {
2315 			msgMouseL->SetLabel(
2316 				(IsAcceptablePoint()) ? (sTexts[406]) : (sNlWx[7])
2317 			);
2318 			msgMouseR->SetLabel(sTexts[407]);
2319 			SetStatusText(sTexts[56]);
2320 		} break;
2321 		case S_LIBELEM_PLACE : {
2322 			msgMouseL->SetLabel(sTexts[411]);
2323 			msgMouseR->SetLabel(sTexts[412]);
2324 			SetStatusText(sTexts[58]);
2325 		} break;
2326 		case S_MOVEPT_SELECT : {
2327 			msgMouseL->SetLabel(
2328 				(NULL != m_pCurrent) ? (sTexts[418]) : (sNlWx[7])
2329 			);
2330 			msgMouseR->SetLabel(sTexts[420]);
2331 			SetStatusText(sTexts[421]);
2332 		} break;
2333 		case S_MOVEPT_PLACE : {
2334 			msgMouseL->SetLabel(sTexts[419]);
2335 			msgMouseR->SetLabel(sTexts[420]);
2336 			SetStatusText(sTexts[421]);
2337 		} break;
2338 		case S_DELPT : {
2339 			msgMouseL->SetLabel(
2340 				(NULL != m_pCurrent) ? (sTexts[431]) : (sNlWx[7])
2341 			);
2342 			msgMouseR->SetLabel(sTexts[432]);
2343 			SetStatusText(sTexts[433]);
2344 		} break;
2345 		case S_ADDPT_SELECT : {
2346 			msgMouseL->SetLabel(
2347 				(NULL != m_pCurrent) ? (sTexts[435]) : (sNlWx[7])
2348 			);
2349 			msgMouseR->SetLabel(sTexts[437]);
2350 			SetStatusText(sTexts[434]);
2351 		} break;
2352 		case S_ADDPT_PLACE : {
2353 			msgMouseL->SetLabel(
2354 				(NULL != m_pCurrent) ? (sTexts[436]) : (sNlWx[7])
2355 			);
2356 			msgMouseR->SetLabel(sTexts[438]);
2357 			SetStatusText(sTexts[434]);
2358 		} break;
2359 		case S_DRWSZ_SELECT : {
2360 			msgMouseL->SetLabel(
2361 				(m_bHaveCornerPoint) ? (sTexts[439]) : (sNlWx[7])
2362 			);
2363 			msgMouseR->SetLabel(sTexts[440]);
2364 			SetStatusText(sTexts[441]);
2365 		} break;
2366 		case S_DRWSZ_PLACE : {
2367 			msgMouseL->SetLabel(sTexts[442]);
2368 			msgMouseR->SetLabel(sTexts[443]);
2369 			SetStatusText(sTexts[441]);
2370 		} break;
2371 		case S_FLIP : {
2372 			msgMouseL->SetLabel(
2373 				(NULL != m_pCurrent) ? (sTexts[445]) : (sNlWx[7])
2374 			);
2375 			msgMouseR->SetLabel(sTexts[446]);
2376 			SetStatusText(sTexts[444]);
2377 		} break;
2378 		case S_GROUP_ONE : {
2379 			int num_marked_2 = wxdobj_num_marked_2(m_pDrw);
2380 			if (NULL != m_pCurrent) {
2381 				msgMouseL->SetLabel(sTexts[
2382 					((wxdobj_is_marked(m_pCurrent,OBJ_MARKER_2))
2383 					? (448) : (447))
2384 				]);
2385 			}
2386 			else {
2387 				msgMouseL->SetLabel(
2388 					(2 <= num_marked_2) ? (sTexts[449]) : (sNlWx[7])
2389 				);
2390 			}
2391 			msgMouseR->SetLabel(sTexts[(2<= num_marked_2) ? (450) : (451)]);
2392 			SetStatusText(sTexts[452]);
2393 		} break;
2394 		case S_UNGROUP : {
2395 			msgMouseL->SetLabel(
2396 				((NULL != m_pCurrent) ? (sTexts[454]) : (sNlWx[7]))
2397 			);
2398 			msgMouseR->SetLabel(sTexts[455]);
2399 			SetStatusText(sTexts[453]);
2400 		} break;
2401 		case S_GROUP_RECT_1 : {
2402 			msgMouseL->SetLabel(sTexts[456]);
2403 			msgMouseR->SetLabel(sTexts[451]);
2404 			SetStatusText(sTexts[457]);
2405 		} break;
2406 		case S_GROUP_RECT_2 : {
2407 			msgMouseL->SetLabel(sTexts[449]);
2408 			msgMouseR->SetLabel(sTexts[450]);
2409 			SetStatusText(sTexts[457]);
2410 		} break;
2411 		case S_DETAILS : case S_DETAILS_2 : {
2412 			msgMouseL->SetLabel(
2413 				(NULL != m_pCurrent) ? (sTexts[459]) : (sNlWx[7])
2414 			);
2415 			msgMouseR->SetLabel(sTexts[460]);
2416 			SetStatusText(sTexts[458]);
2417 		} break;
2418 		case S_CONVERT : {
2419 			switch ( (int)m_iObjToCreate ) {
2420 				case WXD_OT_POLYLINE : {
2421 					SetStatusText(sTexts[546]);
2422 				} break;
2423 				case WXD_OT_POLYGON : {
2424 					SetStatusText(sTexts[545]);
2425 				} break;
2426 				case WXD_OT_C_SPLINE: {
2427 					if (m_bSplineInterpolated) {
2428 						SetStatusText(sTexts[547]);
2429 					}
2430 					else {
2431 						SetStatusText(sTexts[550]);
2432 					}
2433 				} break;
2434 				case WXD_OT_O_SPLINE : {
2435 					if (m_bSplineInterpolated) {
2436 						SetStatusText(sTexts[166]);
2437 					}
2438 					else {
2439 						SetStatusText(sTexts[551]);
2440 					}
2441 				} break;
2442 				case WXD_OT_C_ARC : {
2443 					SetStatusText(sTexts[548]);
2444 				} break;
2445 				case WXD_OT_O_ARC : {
2446 					SetStatusText(sTexts[549]);
2447 				} break;
2448 				case  WXD_OT_DOT_FILLED : {
2449 					SetStatusText(sTexts[553]);
2450 				} break;
2451 				case WXD_OT_DOT_WHITE : {
2452 					SetStatusText(sTexts[552]);
2453 				} break;
2454 			}
2455 			msgMouseL->SetLabel(
2456 				(NULL != m_pCurrent) ? (sTexts[554]) : (sNlWx[7])
2457 			);
2458 			msgMouseR->SetLabel(sTexts[555]);
2459 		} break;
2460 		case S_ROTATE : {
2461 			msgMouseL->SetLabel(
2462 				(NULL != m_pCurrent) ? (sTexts[572]) : (sNlWx[7])
2463 			);
2464 			msgMouseR->SetLabel(sTexts[573]);
2465 			SetStatusText(sTexts[(m_bSplineInterpolated) ? 571 : 570]);
2466 		} break;
2467 		case S_MOD_SPLINE : {
2468 			msgMouseL->SetLabel(
2469 				(NULL != m_pCurrent) ? (sTexts[622]) : (sNlWx[7])
2470 			);
2471 			msgMouseR->SetLabel(sTexts[623]);
2472 			SetStatusText(sTexts[624]);
2473 		} break;
2474 		default : {
2475 		} break;
2476 	}
2477 	/*
2478 		Refresh widgets and update window
2479 	*/
2480 	msgMouseL->Refresh();
2481 	msgMouseM->Refresh();
2482 	msgMouseR->Refresh();
2483 	m_bUpdate = true;
2484 
2485 }
2486 
2487 
2488 
2489 
2490 /* vim: set ai sw=4 ts=4 : */
2491 
2492