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(®ion)) != 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\ä\à\á\â\ã\å\æ\α\ª", 357 "e\è\é\ê\ë\ε\η", 358 "i\ì\í\î\ï\ι", 359 "o\ò\ó\ô\õ\ö\ø\ο\œ", 360 "u\ù\ú\û\ü\μ\υ", 361 362 "A\À\Á\Â\Ã\Ä\Å\Æ\Α\∀", 363 "E\È\É\Ê\Ë\Ε\∃\∈\∉\∋", 364 "I\Ì\Í\Î\Ï\Ι\∫", 365 "O\Ò\Ó\Ô\Ö\Ο", 366 "U\Ù\Ú\Û\Ü\∩\∪\⊂\⊃\⊄", 367 368 "c\ç\©", 369 "C\Ç", 370 371 "$\€\¢\£\¤\¥", 372 "\"\“\”\„\«\»", 373 "'\‘\’\‚\´", 374 "-\–\—\¯\‾\−", 375 "~\˜\∼\≅\≈", 376 "!\¡", 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