1 
2 
3 /* This version of microEmacs is based on the public domain C
4  * version written by Dave G. Conroy.
5  * The D programming language version is written by Walter Bright.
6  * http://www.digitalmars.com/d/
7  * This program is in the public domain.
8  */
9 
10 
11 /*
12  * Due to my (Bjorn Benson) laziness, the functions will all
13  * work with a positive argument, but may or may not with
14  * a negative.
15  */
16 
17 module more;
18 
19 import core.stdc.stdio;
20 
21 import std.ascii;
22 import std.uni;
23 import std.process;
24 
25 import ed;
26 import main;
27 import window;
28 import buffer;
29 import line;
30 import search;
31 import random;
32 import region;
33 import word;
34 import basic;
35 import terminal;
36 import display;
37 import url;
38 import utf;
39 
40 version (Posix)
41 {
42     import core.sys.posix.signal;
43     import core.sys.posix.unistd;
44 }
45 
46 /*
47  * The multiple delete buffers
48  */
49 enum
50 {
51 	DK_CUT,
52 	DK_LINE,
53 	DK_WORD,
54 	DK_CHAR,
55 }
56 
57 void SETMARK()
58 {
59     curwp.w_markp = curwp.w_dotp;
60     curwp.w_marko = curwp.w_doto;
61 }
62 
63 /*
64  * Current direction that things happen in
65  */
66 enum
67 {
68 	ADVANCE,
69 	BACKUP,
70 }
71 
72 int Dcur_direction = ADVANCE;
73 
74 int Dsearch(bool f, int n)
75 {
76 	if( Dcur_direction == ADVANCE )
77 		return( forwsearch(f, n) );
78 	else	return( backsearch(f, n) );
79 }
80 
81 int Dsearchagain(bool f, int n)
82 {
83 	int s;
84 	Dnoask_search = true;
85 	scope(exit) Dnoask_search = false;
86 	if( Dcur_direction == ADVANCE )
87 		s = forwsearch(f, n);
88 	else	s = backsearch(f, n);
89 	return s;
90 }
91 
92 int Ddelline(bool f, int n)
93 {
94 	int s = true;
95 
96 	kill_setbuffer(DK_LINE);
97 	kill_freebuffer();
98 	while( n-- > 0 && s )
99 	{   curwp.w_doto = 0;
100 	    s &= line_delete(llength(curwp.w_dotp) + 1, true);
101 	}
102 	kill_setbuffer(DK_CUT);
103 	return s;
104 }
105 
106 int Dundelline(bool f, int n)
107 {
108 	int s = true;
109 
110 	kill_setbuffer(DK_LINE);
111 	while( n-- > 0 && s )
112 	{
113 		curwp.w_doto = 0;
114 		s = random_yank(true, 1);
115 		backline(false, 1);
116 		curwp.w_doto = 0;
117 	}
118 	kill_setbuffer(DK_CUT);
119 	return s;
120 }
121 
122 int Ddelword(bool f, int n)
123 {
124 	int s = true;
125 
126 	kill_setbuffer(DK_WORD);
127 	kill_freebuffer();
128 	while( n-- > 0 && s )
129 	{
130 		SETMARK();
131 		s = word_forw(false, 1);
132 		if( !s ) break;
133 		s = region_kill(false, 1);
134 	}
135 	kill_setbuffer(DK_CUT);
136 	return s;
137 }
138 
139 int Ddelbword(bool f, int n)
140 {
141 	int s = true;
142 
143 	kill_setbuffer(DK_WORD);
144 	kill_freebuffer();
145 	while( n-- > 0 && s )
146 	{
147 		SETMARK;
148 		s = word_back(false, 1);
149 		if( !s ) break;
150 		s = region_kill(false, 1);
151 	}
152 	kill_setbuffer(DK_CUT);
153 	return s;
154 }
155 
156 int Dundelword(bool f, int n)
157 {
158 	int s = true;
159 
160 	kill_setbuffer(DK_WORD);
161 	while( n-- > 0 && s )
162 		s &= random_yank(true, 1);
163 	kill_setbuffer(DK_CUT);
164 	return s;
165 }
166 
167 int Dadvance(bool f, int n)
168 {
169 	Dcur_direction = ADVANCE;
170 	return true;
171 }
172 
173 int Dbackup(bool f, int n)
174 {
175 	Dcur_direction = BACKUP;
176 	return true;
177 }
178 
179 int Dignore(bool f, int n)
180 {
181 	/* Ignore this command. Useful for ^S and ^Q flow control	*/
182 	/* sent out by some terminals.					*/
183 	return true;
184 }
185 
186 int Dpause(bool f, int n)
187 {
188     version (Posix)
189     {
190 	term.t_move( term.t_nrow - 1, 0 );
191 	term.t_eeop();
192 	term.t_flush();
193 	term.t_close();
194 	killpg(getpgid(0), 18);	/* SIGTSTP -- stop the current program */
195 	term.t_open();
196 	sgarbf = true;
197 	window_refresh(false, 1);
198     }
199     return true;
200 }
201 
202 /*********************************
203  * Decide whether to uppercase a word or a region.
204  */
205 
206 int misc_upper(bool f, int n)
207 {
208     if (curwp.w_markp)
209 	return region_upper(f,n);
210     else
211 	return word_upper(f,n);
212 }
213 
214 /*********************************
215  * Decide whether to lowercase a word or a region.
216  */
217 
218 int misc_lower(bool f, int n)
219 {
220     if (curwp.w_markp)
221 	return region_lower(f,n);
222     else
223 	return word_lower(f,n);
224 }
225 
226 /*********************************
227  * Insert file name and date at top of file.
228  */
229 
230 int Dinsertdate(bool f, int n)
231 {	return false;
232 }
233 
234 /***********************************
235  * Remove trailing whitespace from line.
236  */
237 
238 void deblank()
239 {   int len;
240     int n;
241     int c;
242     int i;
243 
244     len = llength(curwp.w_dotp);
245     for (i = len - 1; i >= 0; i--)
246     {
247 	c = lgetc(curwp.w_dotp, i);
248 	if (!isSpace(c))
249 	    break;
250     }
251     n = (len - 1) - i;
252     if (n)
253     {
254 	curwp.w_doto = i + 1;
255 	line_delete(n,false);
256     }
257 }
258 
259 /*********************************
260  * Convert C comment to C++ comment.
261  */
262 
263 int Dcppcomment(bool f, int n)
264 {
265         int    c;
266         int    i;
267 	LINE *dotpsave;
268 	int dotosave;
269 
270         if (n < 0)
271 	    goto err;
272 	if (window_marking(curwp))
273 	{   REGION region;
274 	    int s;
275 
276 	    if ((s = getregion(&region)) != true)
277 		return s;
278 	    dotpsave = curwp.w_dotp;
279 	    dotosave = curwp.w_doto;
280 	    curwp.w_dotp = region.r_linep;
281 	    curwp.w_doto = region.r_offset;
282 	    n = region.r_nlines;
283 	}
284         while (n--)
285 	{   int len;
286 
287 	    deblank();
288 	    len = llength(curwp.w_dotp);
289 	    if (len)
290 	    {
291 		for (i = 0; i + 3 < len; i++)
292 		{
293 		    c = lgetc(curwp.w_dotp, i);
294 		    if (c == '/' && lgetc(curwp.w_dotp, i + 1) == '*')
295 		    {
296 			if (lgetc(curwp.w_dotp, len - 2) == '*' &&
297 			    lgetc(curwp.w_dotp, len - 1) == '/')
298 			{
299 			    curwp.w_doto = i + 1;
300 			    line_delete(1,false);
301 			    line_insert(1,'/');
302 			    curwp.w_doto = len - 2;
303 			    line_delete(2,false);
304 			    deblank();
305 			    break;
306 			}
307 		    }
308                 }
309 		curwp.w_doto = 0;	/* move to beginning of line	*/
310 	    }
311 	    if (forwline(false,1) == false)
312 		goto err;
313         }
314 	if (window_marking(curwp))
315 	{
316 	    if (dotosave > llength(dotpsave))
317 		dotosave = llength(dotpsave);
318 	    curwp.w_dotp = dotpsave;
319 	    curwp.w_doto = dotosave;
320 	}
321         return true;
322 
323 err:
324 	return false;
325 }
326 
327 /************************************
328  * Open browser on URL.
329  */
330 int openBrowser(bool f, int n)
331 {
332     LINE* dotp = curwp.w_dotp;
333     auto s = getURL(dotp.l_text[0 .. llength(dotp)], curwp.w_doto);
334     if (s)
335     {
336 	browse(cast(string)s);
337 	return TRUE;
338     }
339     return FALSE;
340 }
341 
342 /***************************
343  * Look up current character in the replacement table,
344  * and replace it with the next character in the table.
345  * Returns:
346  *	TRUE = success
347  *	FALSE = failure
348  */
349 
350 int scrollUnicode(bool f, int n)
351 {
352     /* Mapping table of one character to the next in each entry
353      */
354     __gshared immutable string[] table =
355     [
356 	"a\&auml;\&agrave;\&aacute;\&acirc;\&atilde;\&aring;\&aelig;\&alpha;\&ordf;",
357 	"e\&egrave;\&eacute;\&ecirc;\&euml;\&epsilon;\&eta;",
358         "i\&igrave;\&iacute;\&icirc;\&iuml;\&iota;",
359         "o\&ograve;\&oacute;\&ocirc;\&otilde;\&ouml;\&oslash;\&omicron;\&oelig;",
360         "u\&ugrave;\&uacute;\&ucirc;\&uuml;\&mu;\&upsilon;",
361 
362 	"A\&Agrave;\&Aacute;\&Acirc;\&Atilde;\&Auml;\&Aring;\&AElig;\&Alpha;\&forall;",
363 	"E\&Egrave;\&Eacute;\&Ecirc;\&Euml;\&Epsilon;\&exist;\&isin;\&notin;\&ni;",
364 	"I\&Igrave;\&Iacute;\&Icirc;\&Iuml;\&Iota;\&int;",
365 	"O\&Ograve;\&Oacute;\&Ocirc;\&Ouml;\&Omicron;",
366 	"U\&Ugrave;\&Uacute;\&Ucirc;\&Uuml;\&cap;\&cup;\&sub;\&sup;\&nsub;",
367 
368 	"c\&ccedil;\&copy;",
369 	"C\&Ccedil;",
370 
371 	"$\&euro;\&cent;\&pound;\&curren;\&yen;",
372 	"\"\&ldquo;\&rdquo;\&bdquo;\&laquo;\&raquo;",
373 	"'\&lsquo;\&rsquo;\&sbquo;\&acute;",
374 	"-\&ndash;\&mdash;\&macr;\&oline;\&minus;",
375 	"~\&tilde;\&sim;\&cong;\&asymp;",
376 	"!\&iexcl;",
377     ];
378 
379     LINE* dotp = curwp.w_dotp;
380     auto s = dotp.l_text[0 .. llength(dotp)];
381     size_t index = curwp.w_doto;
382 
383     size_t i = index;
384     dchar dc = decodeUTF8(s, i);
385     foreach (entry; table)
386     {
387 	for (size_t j = 0; j < entry.length; )
388 	{
389 	    dchar dr = decodeUTF8(entry, j);
390 	    if (dr == dc)
391 	    {
392 		if (j == entry.length)
393 		    j = 0;
394 		size_t k = j;
395 		decodeUTF8(entry, k);
396 
397 		/* Replace s[index .. i] with entry[j .. k]
398 		 */
399 		line_delete(cast(int)(i - index), FALSE);
400 		foreach (char c; entry[j .. k])
401 		    line_insert(1, c);
402 		backchar(f, cast(int)(k - j));
403 		line_change(WFEDIT);
404 
405 		return TRUE;
406 	    }
407 	}
408     }
409     return FALSE;
410 }
411