1 /* @(#)numbercmds.c	1.19 09/07/09 Copyright 1984-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)numbercmds.c	1.19 09/07/09 Copyright 1984-2009 J. Schilling";
6 #endif
7 /*
8  *	Routines that deal with number and mult.
9  *
10  *	Copyright (c) 1984-2009 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include "ved.h"
27 
28 LOCAL	ecnt_t	mult = (ecnt_t)4;
29 LOCAL	ecnt_t	maxnum = (ecnt_t)0;
30 
31 EXPORT	void	initnum		__PR((void));
32 EXPORT	void	vmult		__PR((ewin_t *wp));
33 EXPORT	void	vsmult		__PR((ewin_t *wp));
34 EXPORT	void	vnum		__PR((ewin_t *wp));
35 LOCAL	void	enumbad		__PR((ewin_t *wp));
36 LOCAL	void	enumoverflow	__PR((ewin_t *wp));
37 LOCAL	void	enumnegative	__PR((ewin_t *wp));
38 
39 /*
40  *  Multiply number with mult.
41  */
42 EXPORT void
initnum()43 initnum()
44 {
45 	ecnt_t	n;
46 	ecnt_t	on;
47 	ecnt_t	a;
48 	int	i;
49 
50 	if (maxnum == 0) {
51 		/*
52 		 * Overflow bei Berechnung von maxnum verhindern
53 		 */
54 		for (i = 0, on = 0, n = (ecnt_t)1; n > 0 && n > on && i < 256; i++) {
55 			on = n;
56 			n  = 2*n;
57 		}
58 		for (i = 0, a = n = on; n > (ecnt_t)0 && n >= on && i < 256; i++) {
59 			on = n;
60 			a /= 2;
61 			if (a < 1)
62 				break;
63 			n  += a;
64 		}
65 		maxnum = on;
66 	}
67 }
68 
69 /*
70  *  Multiply number with mult.
71  */
72 EXPORT void
vmult(wp)73 vmult(wp)
74 	ewin_t	*wp;
75 {
76 	if ((wp->eflags & KEEPDEL) != 0)
77 		wp->eflags |= DELDONE;
78 	wp->eflags &= ~COLUPDATE;
79 
80 	if (wp->number >= maxnum/mult) {
81 		enumoverflow(wp);
82 		return;
83 	}
84 	wp->eflags |= SAVENUM;
85 	wp->number *= mult;
86 	writenum(wp, wp->number);
87 }
88 
89 /*
90  * Set mult.
91  */
92 EXPORT void
vsmult(wp)93 vsmult(wp)
94 	ewin_t	*wp;
95 {
96 	Llong l;
97 	ecnt_t	n;
98 	Uchar	numbuf[NAMESIZE];
99 
100 	if (! getcmdline(wp, numbuf, sizeof (numbuf), "Mult = "))
101 		return;
102 	if (*astoll(C numbuf, &l)) {
103 		enumbad(wp);
104 	} else if (l <= 0) {
105 		enumnegative(wp);
106 	} else {
107 		n = l;
108 		if (n != l) {
109 			enumoverflow(wp);
110 			return;
111 		}
112 		mult = l;
113 	}
114 	wp->eflags &= ~COLUPDATE;
115 }
116 
117 /*
118  * Set number from the commandline.
119  * We already have the first character.
120  * XXX If we bind this to something else than ESC[0-9], we have to rethink.
121  */
122 EXPORT void
vnum(wp)123 vnum(wp)
124 	ewin_t	*wp;
125 {
126 	Llong	l;
127 	ecnt_t	n;
128 	Uchar	numbuf[NAMESIZE];
129 
130 	if (! getccmdline(wp, wp->lastch, numbuf, sizeof (numbuf), "# = "))
131 		return;
132 	if (*astoll(C numbuf, &l)) {
133 		enumbad(wp);
134 	} else if (l <= 0) {
135 		enumnegative(wp);
136 	} else {
137 		n = l;
138 		if (n != l) {
139 			enumoverflow(wp);
140 			return;
141 		}
142 		wp->number = l;
143 		writenum(wp, wp->number);
144 	}
145 	wp->eflags |= SAVENUM;
146 	if ((wp->eflags & KEEPDEL) != 0)
147 		wp->eflags |= DELDONE;
148 }
149 
150 LOCAL void
enumbad(wp)151 enumbad(wp)
152 	ewin_t	*wp;
153 {
154 	writeerr(wp, "Bad Number");
155 }
156 
157 LOCAL void
enumoverflow(wp)158 enumoverflow(wp)
159 	ewin_t	*wp;
160 {
161 	writeerr(wp, "Number Overflow!");
162 }
163 
164 LOCAL void
enumnegative(wp)165 enumnegative(wp)
166 	ewin_t	*wp;
167 {
168 	writeerr(wp, "Must be Positive");
169 }
170