1 // ----------------------------------------------------------------------------
2 // Frequency Control Widget
3 //
4 // Copyright (C) 2014
5 //              David Freese, W1HKJ
6 //
7 // This file is part of flrig.
8 //
9 // flrig is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // flrig is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22 
23 #include <config.h>
24 
25 #include <FL/Fl.H>
26 #include <FL/Fl_Float_Input.H>
27 #include <FL/fl_draw.H>
28 #include <FL/Fl_Box.H>
29 
30 #include <cstdlib>
31 #include <cmath>
32 #include <fstream>
33 
34 #include <stdio.h>
35 
36 #include "fl_digi.h"
37 #include "qrunner.h"
38 
39 #include "FreqControl.h"
40 #include "gettext.h"
41 
42 #include "configuration.h"
43 
44 const char *cFreqControl::Label[10] = {
45 	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
46 
IncFreq(int nbr)47 void cFreqControl::IncFreq (int nbr) {
48 	double v = (double)val + (double)mult[nbr] * precision;
49 	if (v <= maxVal) val = (unsigned long int)v;
50 	updatevalue();
51 	do_callback();
52 }
53 
DecFreq(int nbr)54 void cFreqControl::DecFreq (int nbr) {
55 	double v = (double)val - (double)mult[nbr] * precision;
56 	if (v >= minVal) val = (unsigned long int)v;
57 	updatevalue();
58 	do_callback();
59 }
60 
cbSelectDigit(Fl_Widget * btn,void * nbr)61 void cbSelectDigit (Fl_Widget *btn, void * nbr)
62 {
63 
64 	Fl_Button *b = (Fl_Button *)btn;
65 	int Nbr = reinterpret_cast<intptr_t> (nbr);
66 
67 	cFreqControl *fc = (cFreqControl *)b->parent();
68 	if (fc->hrd_buttons) {
69 		int yclick = Fl::event_y();
70 		int fc_yc = fc->y() + fc->h()/2;
71 		if (yclick <= fc_yc)
72 			fc->IncFreq(Nbr);
73 		else
74 			fc->DecFreq(Nbr);
75 	} else {
76 		if (Fl::event_button1())
77 			fc->IncFreq(Nbr);
78 		else if (Fl::event_button3())
79 			fc->DecFreq(Nbr);
80 	}
81 	fc->redraw();
82 }
83 
84 //#define FCDEBUG 1
85 #ifdef FCDEBUG
86 	static int instance = 0;
87 #endif
88 
cFreqControl(int x,int y,int w,int h,const char * lbl)89 cFreqControl::cFreqControl(int x, int y, int w, int h, const char *lbl):
90 			  Fl_Group(x,y,w,h,"") {
91 	font_number = progdefaults.FreqControlFontnbr;
92 	ONCOLOR = FL_YELLOW;
93 	OFFCOLOR = FL_BLACK;
94 	SELCOLOR = fl_rgb_color(100, 100, 100);
95 	ILLUMCOLOR = FL_GREEN;
96 	oldval = val = 0;
97 	precision = 1;
98 	dpoint = 3;
99 
100 	W = w;
101 	nD = atoi(lbl);
102 	if (nD > MAX_DIGITS) nD = MAX_DIGITS;
103 	if (nD < MIN_DIGITS) nD = MIN_DIGITS;
104 
105 	bdr = 1;
106 	fcHeight = h - 2 * bdr;
107 
108 	int fw, fh, ht = fcHeight;
109 	char widest = '0';
110 
111 	fl_font(font_number, ++ht);
112 	fh = fl_height() + 1;
113 
114 	fw = fl_width(widest);
115 	for (char ch = '1'; ch <= '9'; ch++) {
116 		if (fl_width(ch) > fw) {
117 			widest = ch;
118 			fw = fl_width(ch);
119 		}
120 	}
121 #ifdef FCDEBUG
122 	std::ofstream fc_dump;
123 	if (instance++ == 0) {
124 		fc_dump.open("fc_dump.txt", std::ios::out);
125 	} else {
126 		fc_dump.open("fc_dump.txt", std::ios::app);
127 	}
128 
129 	fc_dump << "=========================================================" << std::endl;
130 	fc_dump << "Frequency Control widget: # " << instance << " : " << this << std::endl;
131 	fc_dump << "---------------------------------------------------------" << std::endl;
132 	fc_dump << "adjust for height" << std::endl;
133 	fc_dump << "fh = font height, fc = control height" << std::endl;
134 	fc_dump << "font " << font_number << ", size " << ht << ", fh >? fc " << fh << " ? " << fcHeight << std::endl;
135 	fc_dump << "widest numeral is " << widest << std::endl;
136 #endif
137 	while (fh > fcHeight) {
138 		--ht;
139 		assert(ht > 0);
140 		fl_font(font_number, ht);
141 		fh = fl_height();
142 #ifdef FCDEBUG
143 	fc_dump << "font " << font_number << ", size " << ht << ", fh >? fc " << fh << " ? " << fcHeight << std::endl;
144 #endif
145 	}
146 
147 	fl_font(font_number, ht);
148 	fw = fl_width(widest) + 4;
149 	pw = fw / 2;
150 #ifdef FCDEBUG
151 	fc_dump << "---------------------------------------------------------" << std::endl;
152 	fc_dump << "adjust for width" << std::endl;
153 	fc_dump << "fw = font width of '0' + 4 pixels for font size 'ht'" << std::endl;
154 	fc_dump << "ht = " << ht << ", fw = " << fw << ", (nD*fw+pw): " << (nD*fw+pw) << ", (W-2*bdr): " << (W-2*bdr) << std::endl;
155 #endif
156 	while( (nD * fw + pw) >= (W - 2*bdr)) {
157 		--ht;
158 		assert(ht > 0);
159 		fl_font(font_number, ht);
160 		fw = fl_width(widest) + 4;
161 #ifdef FCDEBUG
162 	fc_dump << "ht = " << ht << ", fw = " << fw << std::endl;
163 #endif
164 		pw = fw / 2;
165 	}
166 	fh = fl_height();
167 #ifdef FCDEBUG
168 	fc_dump << "---------------------------------------------------------" << std::endl;
169 	fc_dump <<
170 	"font " << font_number << "\n" <<
171 	"size " << ht << "\n" <<
172 	"height in pixels: " << fh << "\n" <<
173 	"width in pixels: " << fw << std::endl;
174 	fc_dump << "=========================================================" << std::endl;
175 	fc_dump.close();
176 #endif
177 
178 	wfill = (w - nD * fw - pw - 2*bdr) / 2;
179 	int wf2 = w - nD * fw - pw - 2*bdr - wfill;
180 
181 	fcWidth = fw;
182 
183 	fcTop = y + bdr;
184 	int xpos;
185 
186 	box(FL_DOWN_BOX);
187 	color(OFFCOLOR);
188 
189 	minVal = 0;
190 	double fmaxval = (pow(10.0, nD) - 1) * precision;
191 	unsigned long int UMAX = maximum();
192 	if (fmaxval > UMAX) fmaxval = UMAX;
193 	maxVal = fmaxval;
194 	fmaxval /= 1000.0;
195 
196 	static char tt[100];
197 	snprintf(tt, sizeof(tt), "Enter frequency (max %.3f) or\nLeft/Right/Up/Down/Pg_Up/Pg_Down", fmaxval);
198 	tooltip(tt);
199 
200 	hfill2 = new Fl_Box(x + w - bdr - wf2, fcTop, wf2, fcHeight, "");
201 	hfill2->box(FL_FLAT_BOX);
202 	hfill2->labelcolor(ONCOLOR);
203 	hfill2->color(OFFCOLOR);
204 
205 	xpos = x + w - bdr - wfill;
206 	for (int n = 0; n < 3; n++) {
207 		xpos -= fcWidth;
208 		Digit[n] = new Fl_Repeat_Button (
209 			xpos,
210 			fcTop,
211 			fcWidth,
212 			fcHeight,
213 			" ");
214 		Digit[n]->box(FL_FLAT_BOX);
215 		Digit[n]->labelfont(font_number);
216 		Digit[n]->labelcolor(ONCOLOR);
217 		Digit[n]->color(OFFCOLOR, SELCOLOR);
218 		Digit[n]->labelsize(fh);
219 		Digit[n]->callback(cbSelectDigit, reinterpret_cast<void*>(n));
220 		if (n == 0) mult[n] = 1;
221 		else mult[n] = 10 * mult[n-1];
222 	}
223 
224 	xpos -= pw;
225 	decbx = new Fl_Box(xpos, fcTop, pw, fcHeight,".");
226 	decbx->box(FL_FLAT_BOX);
227 	decbx->labelfont(font_number);
228 	decbx->labelcolor(ONCOLOR);
229 	decbx->color(OFFCOLOR);
230 	decbx->labelsize(fh);
231 
232 	for (int n = 3; n < nD; n++) {
233 		xpos -= fcWidth;
234 		Digit[n] = new Fl_Repeat_Button (
235 			xpos,
236 			fcTop,
237 			fcWidth,
238 			fcHeight,
239 			" ");
240 		Digit[n]->box(FL_FLAT_BOX);
241 		Digit[n]->labelfont(font_number);
242 		Digit[n]->labelcolor(ONCOLOR);
243 		Digit[n]->color(OFFCOLOR, SELCOLOR);
244 		Digit[n]->labelsize(fh);
245 		Digit[n]->callback(cbSelectDigit, reinterpret_cast<void*>(n));
246 		if (n == 0) mult[n] = 1;
247 		else mult[n] = 10 * mult[n-1];
248 	}
249 
250 	hfill1 = new Fl_Box(x + bdr, fcTop, Digit[nD-1]->x() - x - bdr, fcHeight, "");
251 	hfill1->box(FL_FLAT_BOX);
252 	hfill1->labelcolor(ONCOLOR);
253 	hfill1->color(OFFCOLOR);
254 
255 	cbFunc = NULL;
256 	end();
257 
258 	finp = new Fl_Float_Input(0, 0, 24,24);//1, 1);
259 	finp->callback(freq_input_cb, this);
260 	finp->when(FL_WHEN_CHANGED);
261 
262 	parent()->remove(finp);
263 
264 	precision = 1;
265 	hrd_buttons = true;
266 	enable_arrow_keys = false;
267 
268 }
269 
~cFreqControl()270 cFreqControl::~cFreqControl()
271 {
272 	for (int i = 0; i < nD; i++) {
273 		delete Digit[i];
274 	}
275 	delete finp;
276 }
277 
278 
updatevalue()279 void cFreqControl::updatevalue()
280 {
281 	unsigned long int v = val / precision;
282 	int i;
283 	if (likely(v > 0L)) {
284 		for (i = 0; i < nD; i++) {
285 			Digit[i]->label(v == 0 ? "" : Label[v % 10]);
286 			v /= 10;
287 		}
288 	}
289 	else {
290 		for (i = 0; i < 4; i++)
291 			Digit[i]->label("0");
292 		for (; i < nD; i++)
293 			Digit[i]->label("");
294 	}
295 	decbx->label(".");
296 	decbx->redraw_label();
297 	redraw();
298 }
299 
font(Fl_Font fnt)300 void cFreqControl::font(Fl_Font fnt)
301 {
302 	font_number = fnt;
303 	set_ndigits(nD);
304 	updatevalue();
305 }
306 
SetONOFFCOLOR(Fl_Color ONcolor,Fl_Color OFFcolor)307 void cFreqControl::SetONOFFCOLOR( Fl_Color ONcolor, Fl_Color OFFcolor)
308 {
309 	OFFCOLOR = REVONCOLOR = OFFcolor;
310 	ONCOLOR = REVOFFCOLOR = ONcolor;
311 
312 	for (int n = 0; n < nD; n++) {
313 		Digit[n]->labelcolor(ONCOLOR);
314 		Digit[n]->color(OFFCOLOR);
315 		Digit[n]->redraw();
316 		Digit[n]->redraw_label();
317 	}
318 	decbx->labelcolor(ONCOLOR);
319 	decbx->color(OFFCOLOR);
320 	decbx->redraw();
321 	decbx->redraw_label();
322 	hfill1->labelcolor(ONCOLOR);
323 	hfill1->color(OFFCOLOR);
324 	hfill1->redraw();
325 	hfill1->redraw_label();
326 	hfill2->labelcolor(ONCOLOR);
327 	hfill2->color(OFFCOLOR);
328 	hfill2->redraw();
329 	hfill2->redraw_label();
330 	color(OFFCOLOR);
331 	redraw();
332 }
333 
SetONCOLOR(uchar r,uchar g,uchar b)334 void cFreqControl::SetONCOLOR (uchar r, uchar g, uchar b)
335 {
336 	ONCOLOR = fl_rgb_color (r, g, b);
337 	REVOFFCOLOR = ONCOLOR;
338 	for (int n = 0; n < nD; n++) {
339 		Digit[n]->labelcolor(ONCOLOR);
340 		Digit[n]->color(OFFCOLOR);
341 		Digit[n]->redraw();
342 		Digit[n]->redraw_label();
343 	}
344 	decbx->labelcolor(ONCOLOR);
345 	decbx->color(OFFCOLOR);
346 	decbx->redraw();
347 	decbx->redraw_label();
348 	hfill1->color(OFFCOLOR);
349 	hfill1->labelcolor(ONCOLOR);
350 	hfill1->redraw();
351 	hfill1->redraw_label();
352 	hfill2->labelcolor(ONCOLOR);
353 	hfill2->color(OFFCOLOR);
354 	hfill2->redraw();
355 	hfill2->redraw_label();
356 	color(OFFCOLOR);
357 	redraw();
358 }
359 
SetOFFCOLOR(uchar r,uchar g,uchar b)360 void cFreqControl::SetOFFCOLOR (uchar r, uchar g, uchar b)
361 {
362 	OFFCOLOR = fl_rgb_color (r, g, b);
363 	REVONCOLOR = OFFCOLOR;
364 
365 	for (int n = 0; n < nD; n++) {
366 		Digit[n]->labelcolor(ONCOLOR);
367 		Digit[n]->color(OFFCOLOR);
368 	}
369 	decbx->labelcolor(ONCOLOR);
370 	decbx->color(OFFCOLOR);
371 	decbx->redraw();
372 	decbx->redraw_label();
373 	hfill1->color(OFFCOLOR);
374 	hfill1->labelcolor(ONCOLOR);
375 	hfill1->redraw();
376 	hfill1->redraw_label();
377 	hfill2->labelcolor(ONCOLOR);
378 	hfill2->color(OFFCOLOR);
379 	hfill2->redraw();
380 	hfill2->redraw_label();
381 	color(OFFCOLOR);
382 	redraw();
383 }
384 
blink_point(Fl_Widget * w)385 static void blink_point(Fl_Widget* w)
386 {
387 	w->label(*w->label() ? "" : ".");
388 	Fl::add_timeout(0.2, (Fl_Timeout_Handler)blink_point, w);
389 }
390 
value(unsigned long int lv)391 void cFreqControl::value(unsigned long int lv)
392 {
393 	oldval = val = lv;
394 	Fl::remove_timeout((Fl_Timeout_Handler)blink_point, decbx);
395 	updatevalue();
396 }
397 
maximum(void)398 unsigned long int cFreqControl::maximum(void)
399 {
400 	return (unsigned long int)(pow(2.0, 32) - 1);
401 }
402 
403 
restore_colors()404 void cFreqControl::restore_colors()
405 {
406 	enable_arrow_keys = false;
407 	for (int n = 0; n < nD; n++) {
408 		Digit[n]->labelcolor(ONCOLOR);
409 		Digit[n]->color(OFFCOLOR);
410 		Digit[n]->redraw();
411 		Digit[n]->redraw_label();
412 	}
413 	decbx->labelcolor(ONCOLOR);
414 	decbx->color(OFFCOLOR);
415 	decbx->redraw();
416 	decbx->redraw_label();
417 	hfill1->labelcolor(ONCOLOR);
418 	hfill1->color(OFFCOLOR);
419 	hfill1->redraw();
420 	hfill1->redraw_label();
421 	hfill2->labelcolor(ONCOLOR);
422 	hfill2->color(OFFCOLOR);
423 	hfill2->redraw();
424 	hfill2->redraw_label();
425 	color(OFFCOLOR);
426 	redraw();
427 }
428 
reverse_colors()429 void cFreqControl::reverse_colors()
430 {
431 	enable_arrow_keys = true;
432 	for (int n = 0; n < nD; n++) {
433 		Digit[n]->labelcolor(REVONCOLOR);
434 		Digit[n]->color(REVOFFCOLOR);
435 		Digit[n]->redraw();
436 		Digit[n]->redraw_label();
437 	}
438 	decbx->labelcolor(REVONCOLOR);
439 	decbx->color(REVOFFCOLOR);
440 	decbx->redraw();
441 	decbx->redraw_label();
442 	hfill1->labelcolor(REVONCOLOR);
443 	hfill1->color(REVOFFCOLOR);
444 	hfill1->redraw();
445 	hfill1->redraw_label();
446 	hfill2->labelcolor(REVONCOLOR);
447 	hfill2->color(REVOFFCOLOR);
448 	hfill2->redraw();
449 	hfill2->redraw_label();
450 	color(REVOFFCOLOR);
451 	redraw();
452 }
453 
454 #define KEEP_FOCUS (void *)0
455 #define LOSE_FOCUS (void *)1
456 
cancel_kb_entry(void)457 void cFreqControl::cancel_kb_entry(void)
458 {
459 	val = oldval;
460 	Fl::remove_timeout((Fl_Timeout_Handler)blink_point, decbx);
461 	updatevalue();
462 }
463 
handle(int event)464 int cFreqControl::handle(int event)
465 {
466 //	static Fl_Widget* fw = NULL;
467 	int d;
468 
469 	switch (event) {
470 
471 	case FL_FOCUS:
472 		return 1;
473 	case FL_UNFOCUS:
474 		return 1;
475 	case FL_ENTER:
476 //		fw = Fl::focus();
477 //		if (fw != NULL) // if NULL then fldigi did not have focus
478 //			take_focus();
479 		break;
480 	case FL_LEAVE:
481 //		if (fw)
482 //			fw->take_focus();
483 //		if (Fl::has_timeout((Fl_Timeout_Handler)blink_point, this))
484 //			cancel_kb_entry();
485 //		clear_focus();
486 //		updatevalue();
487 //		return 1;
488 		break;
489 
490 	case FL_KEYBOARD:
491 		switch (d = Fl::event_key()) {
492 		case FL_Right:
493 			if (Fl::event_shift())
494 				d = 100 * lsd;
495 			else
496 				d = lsd;
497 			val += d;
498 			updatevalue();
499 			do_callback();
500 			return 1;
501 			break;
502 		case FL_Left:
503 			if (Fl::event_shift())
504 				d = -100 * lsd;
505 			else
506 				d = -1 * lsd;
507 			val += d;
508 			updatevalue();
509 			do_callback();
510 			return 1;
511 			break;
512 		case FL_Up:
513 			if (Fl::event_shift())
514 				d = 1000 * lsd;
515 			else
516 				d = 10 * lsd;
517 			val += d;
518 			updatevalue();
519 			do_callback();
520 			return 1;
521 			break;
522 		case FL_Down:
523 			if (Fl::event_shift())
524 				d = -1000 * lsd;
525 			else
526 				d = -10 * lsd;
527 			val += d;
528 			updatevalue();
529 			do_callback();
530 			return 1;
531 			break;
532 		default:
533 			if (Fl::event_ctrl()) {
534 				if (Fl::event_key() == 'v') {
535 					finp->handle(event);
536 					Fl::remove_timeout((Fl_Timeout_Handler)blink_point, decbx);
537 					return 1;
538 				}
539 			}
540 			if (Fl::has_timeout((Fl_Timeout_Handler)blink_point, decbx)) {
541 				if (d == FL_Escape) {
542 					cancel_kb_entry();
543 					return 1;
544 				}
545 				else if (d == FL_Enter || d == FL_KP_Enter) {
546 					finp->position(finp->size());
547 					finp->replace(finp->position(), finp->mark(), "\n", 1);
548 					clear_focus();
549 					updatevalue();
550 					do_callback();
551 					return 1;
552 				}
553 			}
554 			else {
555 				if (d == FL_Escape && window() != Fl::first_window()) {
556 					window()->do_callback();
557 					return 1;
558 				} else if (d == FL_Enter) {
559 					clear_focus();
560 					updatevalue();
561 					do_callback();
562 					return 1;
563 				}
564 				int ch = Fl::event_text()[0];
565 				if (ch < '0' || ch > '9') return Fl_Group::handle(event);
566 				Fl::add_timeout(0.0, (Fl_Timeout_Handler)blink_point, decbx);
567 				finp->static_value("");
568 				oldval = val;
569 				if (!enable_arrow_keys) reverse_colors();
570 			}
571 			return finp->handle(event);
572 		}
573 		val += d;
574 		updatevalue();
575 		do_callback();
576 		break;
577 	case FL_MOUSEWHEEL:
578 		if ( !((d = Fl::event_dy()) || (d = Fl::event_dx())) )
579 			return 1;
580 
581 		for (int i = 0; i < nD; i++) {
582 			if (Fl::event_inside(Digit[i])) {
583 				d > 0 ? DecFreq(i) : IncFreq(i);
584 				return 1;//break;
585 			}
586 		}
587 		break;
588 	case FL_PUSH:
589 		if (Fl::event_button() == FL_MIDDLE_MOUSE)
590 			Fl::paste(*this, 0);
591 		else
592 			return Fl_Group::handle(event);
593 		break;
594 	case FL_PASTE:
595 		finp->value(Fl::event_text());
596 		finp->position(finp->size());
597 		finp->insert(" \n", 2); // space before newline for pasted text
598 		finp->do_callback();
599 		break;
600 	}
601 	return Fl_Group::handle(event);
602 }
603 
freq_input_cb(Fl_Widget *,void * arg)604 void cFreqControl::freq_input_cb(Fl_Widget*, void* arg)
605 {
606 	cFreqControl* fc = reinterpret_cast<cFreqControl*>(arg);
607 	double val = strtod(fc->finp->value(), NULL);
608 	unsigned long int lval;
609 	val *= 1e3;
610 	val += 0.5;
611 	lval = (long)val;
612 	if (lval <= fc->maxVal) {
613 		fc->val = (long)val;
614 		fc->updatevalue();
615 		if (fc->finp->index(fc->finp->size() - 1) == '\n' && val > 0.0) {
616 			Fl::remove_timeout((Fl_Timeout_Handler)blink_point, fc->decbx);
617 			fc->do_callback();
618 		}
619 	}
620 }
621 
restore_color(void * w)622 static void restore_color(void* w)
623 {
624 	cFreqControl *fc = (cFreqControl *)w;
625 	fc->restore_colors();
626 }
627 
visual_beep()628 void cFreqControl::visual_beep()
629 {
630 	reverse_colors();
631 	Fl::add_timeout(0.1, restore_color, this);
632 }
633 
set_ndigits(int nbr)634 void cFreqControl::set_ndigits(int nbr)
635 {
636 	delete decbx;
637 	for (int n = 0; n < nD; n++) {
638 		this->remove(Digit[n]);
639 		delete Digit[n];
640 	}
641 
642 	nD = nbr;
643 	if (nD > MAX_DIGITS) nD = MAX_DIGITS;
644 	if (nD < MIN_DIGITS) nD = MIN_DIGITS;
645 
646 	int fw, fh, ht = h() - 2*bdr;
647 
648 	font_number = progdefaults.FreqControlFontnbr;
649 
650 	fl_font(font_number, ht);
651 	fh = fl_height();// + 1;
652 	while (fh > fcHeight) {
653 		ht--;
654 		fl_font(font_number, ht);
655 		fh = fl_height();
656 	}
657 
658 	fl_font(font_number, ht);
659 	fw = fl_width("9") + 2;
660 	pw = fw / 2;
661 	while( (nD * fw + pw) >= (W - 2*bdr)) {
662 		ht--;
663 		fl_font(font_number, ht);
664 		fw = fl_width("9") + 2;
665 		pw = fw / 2;
666 	}
667 	fh = fl_height();
668 	fcWidth = fw;
669 
670 	int wf1 = (w() - nD * fcWidth - pw - 2*bdr)/2;
671 	int wf2 = w() - nD * fcWidth - pw - 2*bdr - wf1;
672 
673 	fcTop = y() + bdr;
674 	int xpos;
675 
676 	minVal = 0;
677 	double fmaxval = (pow(10.0, nD) - 1) * precision;
678 	unsigned long int UMAX = (unsigned long int)(pow(2.0, 32) - 1);
679 	if (fmaxval > UMAX) fmaxval = UMAX;
680 	maxVal = fmaxval;
681 	fmaxval /= 1000.0;
682 
683 	static char tt[100];
684 	snprintf(tt, sizeof(tt), "Enter frequency (max %.3f) or\nLeft/Right/Up/Down/Pg_Up/Pg_Down", fmaxval);
685 	tooltip(tt);
686 
687 	hfill2->resize(x() + w() - bdr - wf2, fcTop, wf2, fcHeight);
688 
689 	xpos = x() + w() - bdr - wf2;
690 	for (int n = 0; n < dpoint; n++) {
691 		xpos -= fcWidth;
692 		Digit[n] = new Fl_Repeat_Button (
693 			xpos,
694 			fcTop,
695 			fcWidth,
696 			fcHeight,
697 			" ");
698 		Digit[n]->box(FL_FLAT_BOX);
699 		Digit[n]->labelfont(font_number);
700 		Digit[n]->labelcolor(ONCOLOR);
701 		Digit[n]->color(OFFCOLOR, SELCOLOR);
702 		Digit[n]->labelsize(fh);
703 		Digit[n]->callback(cbSelectDigit, reinterpret_cast<void*>(n));
704 		if (n == 0) mult[n] = 1;
705 		else mult[n] = 10 * mult[n-1];
706 		this->add(Digit[n]);
707 	}
708 
709 	xpos -= pw;
710 	decbx = new Fl_Box(xpos, fcTop, pw, fcHeight,".");
711 	decbx->box(FL_FLAT_BOX);
712 	decbx->labelfont(font_number);
713 	decbx->labelcolor(ONCOLOR);
714 	decbx->color(OFFCOLOR);
715 	decbx->labelsize(fh);
716 	this->add(decbx);
717 
718 	for (int n = dpoint; n < nD; n++) {
719 		xpos -= fcWidth;
720 		Digit[n] = new Fl_Repeat_Button (
721 			xpos,
722 			fcTop,
723 			fcWidth,
724 			fcHeight,
725 			" ");
726 		Digit[n]->box(FL_FLAT_BOX);
727 		Digit[n]->labelfont(font_number);
728 		Digit[n]->labelcolor(ONCOLOR);
729 		Digit[n]->color(OFFCOLOR, SELCOLOR);
730 		Digit[n]->labelsize(fh);
731 		Digit[n]->callback(cbSelectDigit, reinterpret_cast<void*>(n));
732 		if (n == 0) mult[n] = 1;
733 		else mult[n] = 10 * mult[n-1];
734 		this->add(Digit[n]);
735 	}
736 
737 	hfill1->resize(x() + bdr, fcTop, wf1, fcHeight);
738 
739 	redraw();
740 }
741 
resize(int x,int y,int w,int h)742 void cFreqControl::resize(int x, int y, int w, int h)
743 {
744 	Fl_Group::resize(x,y,w,h);
745 
746 	int wf1 = (w - nD * fcWidth - pw - 2*bdr) / 2;
747 	int wf2 = w - nD * fcWidth - pw - 2*bdr - wf1;
748 
749 	hfill2->resize(x + w - bdr - wf2, y + bdr, wf2, h - 2*bdr);
750 
751 	int xpos = x + w - bdr - wf2;
752 	int ypos = y + bdr;
753 	for (int n = 0; n < dpoint; n++) {
754 		xpos -= fcWidth;
755 		Digit[n]->resize(xpos, ypos, fcWidth, fcHeight);
756 	}
757 
758 	xpos -= pw;
759 	decbx->resize(xpos, ypos, pw, fcHeight);
760 
761 	for (int n = dpoint; n < nD; n++) {
762 		xpos -= fcWidth;
763 		Digit[n]->resize(xpos, ypos, fcWidth, fcHeight);
764 	}
765 
766 	hfill1->resize(x + bdr, y + bdr, wf1, h - 2*bdr);
767 
768 	Fl_Group::redraw();
769 }
770