1 /*
2  * @(#)text.c	1.2	01/03/85
3  *
4  * Text subwindow routines for the SUN Gremlin picture editor.
5  *
6  * Mark Opperman (opcode@monet.BERKELEY)
7  *
8  */
9 
10 #include <suntool/tool_hs.h>
11 #include <sgtty.h>
12 #include "gremlin.h"
13 #include "icondata.h"
14 
15 /* imports from main.c */
16 
17 extern struct pixwin *text_pw;
18 extern struct rect text_size;
19 extern TOOLINSTALLED;
20 extern (*lastcommand)();
21 extern lasttext;
22 
23 /* imports from long.c */
24 
25 extern LGTextSW();
26 
27 /* imports from graphics.c */
28 
29 extern GRCurrentSetOn();
30 
31 /* imports from help.c */
32 
33 extern textsw_help();
34 extern get_any_button();
35 
36 /* locals */
37 
38 struct pixfont *text_pf;
39 
40 #define TEXT_LEFT 96		/* start of text input */
41 #define TEXT_FIRST  ' '
42 #define TEXT_LAST  '~'
43 #define CTRL_W  '\027'
44 #define RETURN  '\r'
45 #define MSGLINE 17
46 
47 #define text_width  (text_pf->pf_defaultsize.x)
48 #define text_height  (text_pf->pf_defaultsize.y)
49 
50 static char text_buf[TEXT_BUFMAX] = "";
51 static char mesg_buf[TEXT_BUFMAX] = "";
52 static char save_buf[TEXT_BUFMAX] = "";
53 static char text_erase;
54 static char text_kill;
55 static char text_erase_word;
56 static text_length;
57 static mesg_length;	/* length of last message displayed */
58 static putmsg = FALSE;	/* TRUE if TxPutMsg called since last button input. */
59 
60 
61 void
62 text_cursor(op)
63 int op;
64 {
65     pw_write(text_pw, TEXT_LEFT + text_length * text_width, 0,
66 		text_width, text_height, op, &bigblack_pr, 0, 0);
67 }
68 
69 
70 void
71 text_output(c)
72 register c;
73 {
74     register count;
75 
76     TxMsgOK();
77 
78     if ((c>=TEXT_FIRST) && (c<=TEXT_LAST) && (text_length<TEXT_BUFMAX-1)) {
79 	text_buf[text_length] = c;
80 	text_buf[text_length+1] = '\0';
81 	pw_char(text_pw, TEXT_LEFT + text_length * text_width, TEXT_BASELINE,
82 			PIX_SRC, text_pf, c);
83 	text_length++;
84 	text_cursor(PIX_SRC);
85     }
86 
87     else if ((c == text_erase) && (text_length > 0)) {
88 	text_cursor(PIX_NOT(PIX_SRC));
89 	text_length--;
90 	pw_char(text_pw, TEXT_LEFT + text_length * text_width,
91 		TEXT_BASELINE, PIX_SRC^PIX_DST, text_pf, text_buf[text_length]);
92 	text_buf[text_length] = '\0';
93 	text_cursor(PIX_SRC);
94     }
95 
96     else if (c == text_kill) {
97 	TxKillLine();
98     }
99 
100     else if ((c == text_erase_word) && (text_length > 0)) {
101 	text_cursor(PIX_NOT(PIX_SRC));
102 	count = 0;
103 	while ((text_length > 0) && (text_buf[text_length-1] == ' ')) {
104 	    text_length--;
105 	    count++;
106 	}
107 	while ((text_length > 0) && (text_buf[text_length-1] != ' ')) {
108 	    text_length--;
109 	    count++;
110 	}
111 	text_buf[text_length] = '\0';
112 	pw_replrop(text_pw, TEXT_LEFT + text_length * text_width, 0,
113 			count * text_width, text_height, PIX_NOT(PIX_SRC),
114 			&bigblack_pr, 0, 0);
115 	text_cursor(PIX_SRC);
116     }
117 
118     else if (c == RETURN) {	/* new text entry method */
119 	lastcommand = LGTextSW;
120 	lasttext = TRUE;
121 	LGTextSW();
122     }
123 }
124 
125 
126 text_getvalue(s)
127 register char *s;
128 {
129     register i = 0;
130 
131     while (text_buf[i] == ' ')
132 	i++;
133 
134     (void) strcpy(save_buf, &text_buf[i]);
135     (void) strcpy(s, &text_buf[i]);
136 }
137 
138 
139 text_putvalue()
140 {
141     pw_text(text_pw, 2, TEXT_BASELINE, PIX_SRC,
142 				text_pf, "text input:");
143     pw_text(text_pw, TEXT_LEFT, TEXT_BASELINE, PIX_SRC,
144 				text_pf, text_buf);
145     text_cursor(PIX_SRC);
146     pw_text(text_pw, 0, MSGLINE + TEXT_BASELINE, PIX_NOT(PIX_SRC),
147 				text_pf, mesg_buf);
148 }
149 
150 
151 text_restorebuf()
152 {
153     register char *s;
154 
155     TxKillLine();
156     s = save_buf;
157     while (*s)
158 	text_output(*s++);
159 }
160 
161 
162 text_left(ie)
163 register struct inputevent *ie;
164 {
165     TxMsgOK();
166 }
167 
168 
169 text_middle(ie)
170 register struct inputevent *ie;
171 {
172     TxMsgOK();
173     text_restorebuf();
174 }
175 
176 
177 text_right(ie)
178 register struct inputevent *ie;
179 {
180     TxMsgOK();
181     textsw_help();
182 }
183 
184 
185 text_winexit(ie)
186 register struct inputevent *ie;
187 {
188     /* check for leaving tool */
189     if ((ie->ie_locy < 0) || (ie->ie_locx < 0) ||
190 			     (ie->ie_locx >= text_size.r_width))
191 	GRCurrentSetOn();
192 }
193 
194 
195 TxInit()
196 {
197     struct sgttyb sgtty_buf;
198 
199     ioctl(fileno(stdin), TIOCGETP, &sgtty_buf);
200     text_erase = sgtty_buf.sg_erase;
201     text_kill = sgtty_buf.sg_kill;
202     text_erase_word = CTRL_W;
203 
204     text_length = mesg_length = 0;
205     text_buf[0] = mesg_buf[0] = '\0';
206 
207     text_pf = pf_open("/usr/suntool/fixedwidthfonts/gacha.r.7");
208 
209     if (text_pf == (struct pixfont*) NULL) {
210 	printf("TxInit: error opening text_pf font file\n");
211 	exit(1);
212     }
213 }  /* end TxInit */
214 
215 
216 /*
217  * This routine marks it OK to output messages again
218  * just as if a button had been pressed.
219  */
220 TxMsgOK()
221 {
222     if (putmsg) {        /* message on the screen to be blanked */
223 	TxClearMsg();
224     }
225 
226     putmsg = FALSE;
227 }  /* end TxMsgOK */
228 
229 
230 /*
231  * Output a one line message into the text subwindow.
232  * If the message follows another without intervening user input,
233  * the prompt "More" is output and we wait for a button input event
234  * before displaying the new message.
235  */
236 TxPutMsg(msg)
237 register char *msg;
238 {
239     if (!TOOLINSTALLED) {		/* tool not displayed yet */
240 	fprintf(stderr, "%s\n", msg);
241 	return;
242     }
243 
244     if (putmsg) {
245 	pw_text(text_pw, mesg_length * text_width, MSGLINE+TEXT_BASELINE,
246 		    PIX_SRC, text_pf, " --More--");
247 	get_any_button();
248 	TxClearMsg();
249     }
250 
251     pw_text(text_pw, 0, MSGLINE+TEXT_BASELINE, PIX_NOT(PIX_SRC), text_pf, msg);
252 
253     putmsg = TRUE;
254     mesg_length = strlen(msg);
255     (void) strcpy(mesg_buf, msg);
256 }  /* end TxPutMsg */
257 
258 
259 /*
260  * Clear current message.
261  */
262 TxClearMsg()
263 {
264     pw_replrop(text_pw, 0, MSGLINE, 2000, text_height,
265 				PIX_NOT(PIX_SRC), &bigblack_pr, 0, 0);
266     mesg_length = 0;
267     mesg_buf[0] = '\0';
268 }
269 
270 
271 /*
272  * Consume user text parameter - don't touch message area.
273  */
274 TxKillLine()
275 {
276     if (text_length > 0) {
277 	pw_replrop(text_pw, TEXT_LEFT, 0, 2000, text_height,
278 					PIX_NOT(PIX_SRC), &bigblack_pr, 0, 0);
279 	text_length = 0;
280 	text_buf[0] = '\0';
281 	text_cursor(PIX_SRC);
282     }
283 }
284