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 * This program is in public domain; written by Dave G. Conroy. 12 * This file contains the main driving routine, and some keyboard processing 13 * code, for the MicroEMACS screen editor. 14 * 15 * REVISION HISTORY: 16 * 17 * 1.0 Steve Wilhite, 30-Nov-85 18 * - Removed the old LK201 and VT100 logic. Added code to support the 19 * DEC Rainbow keyboard (which is a LK201 layout) using the the Level 20 * 1 Console In ROM INT. See "rainbow.h" for the function key definitions. 21 * 22 * 2.0 George Jones, 12-Dec-85 23 * - Ported to Amiga. 24 * 25 * Later versions - Walter Bright, Bjorn Benson 26 * - Ported to linux 27 * - Ported to Win32 (compile with Digital Mars C compiler, www.digitalmars.com) 28 * - Ported to DOS32 29 * 30 * The D programming language version 31 * - translated to D by Walter Bright on 14-Feb-2008 32 * - drops 16 bit versions, all versions other than Windows and Linux 33 */ 34 35 module main; 36 37 import core.stdc.time; 38 import core.stdc.stdlib; 39 40 import std..string; 41 import std.stdio; 42 import std.utf; 43 44 import ed; 45 import file; 46 import buffer; 47 import window; 48 import basic; 49 import random; 50 import more; 51 import search; 52 import region; 53 import word; 54 import spawn; 55 import display; 56 import terminal; 57 import line; 58 import mouse; 59 import console; 60 61 int currow; /* Working cursor row */ 62 int fillcol; /* Current fill column */ 63 int thisflag; /* Flags, this command */ 64 int lastflag; /* Flags, last command */ 65 int curgoal; /* Goal column */ 66 int markcol; /* starting column for column cut */ 67 int hasmouse; /* TRUE if we have a mouse */ 68 BUFFER *curbp; /* Current buffer */ 69 WINDOW *curwp; /* Current window */ 70 BUFFER *bheadp; /* BUFFER listhead */ 71 BUFFER *blistp; /* Buffer list BUFFER */ 72 dchar[256] kbdm = [CTLX|')']; /* Macro */ 73 dchar *kbdmip; /* Input for above */ 74 dchar *kbdmop; /* Output for above */ 75 string pat; /* search pattern */ 76 ubyte insertmode = 1; /* insert/overwrite mode */ 77 string progname; /* this program name */ 78 79 /+ 80 int basic_nextline(); /* Move to next line */ 81 int basic_setmark(); /* Set mark */ 82 83 int random_setfillcol(); /* Set fill column. */ 84 int random_showcpos(); /* Show the cursor position */ 85 int random_twiddle(); /* Twiddle characters */ 86 int random_tab(); /* Insert tab */ 87 int random_hardtab(); // Set hardware tabs 88 int random_newline(); /* Insert CR-LF */ 89 int random_indent(); /* Insert CR-LF, then indent */ 90 int random_incindent(); /* increase indentation level */ 91 int random_decindent(); /* decrease indentation level */ 92 int random_opttab(); /* optimize tabbing in line */ 93 int random_openline(); /* Open up a blank line */ 94 int random_deblank(); /* Delete blank lines */ 95 int random_quote(); /* Insert literal */ 96 int random_forwdel(); /* Forward delete */ 97 int random_backdel(); /* Backward delete */ 98 int random_kill(); /* Kill forward */ 99 int random_yank(); /* Yank back from killbuffer. */ 100 int random_undelchar(); /* Undelete a character */ 101 102 int region_togglemode(); /* Toggle column region mode */ 103 int region_kill(); /* Kill region. */ 104 int region_copy(); /* Copy region to kill buffer. */ 105 106 int window_next(); /* Move to the next window */ 107 int window_prev(); /* Move to the previous window */ 108 int window_only(); /* Make current window only one */ 109 int window_split(); /* Split current window */ 110 int window_mvdn(); /* Move window down */ 111 int window_mvup(); /* Move window up */ 112 int window_enlarge(); /* Enlarge display window */ 113 int window_shrink(); /* Shrink window */ 114 int window_reposition(); /* Reposition window */ 115 int window_refresh(); /* Refresh the screen */ 116 117 int toggleinsert(); /* Toggle insert/overwrite mode */ 118 int line_overwrite(); /* Write char in overwrite mode */ 119 int ctrlg(); /* Abort out of things */ 120 int quit(); /* Quit */ 121 int main_saveconfig(); /* Save configuration */ 122 int ctlxlp(); /* Begin macro */ 123 int ctlxrp(); /* End macro */ 124 int macrotoggle(); /* Start/End macro */ 125 int ctlxe(); /* Execute macro */ 126 int filenext(); /* Edit next file */ 127 int fileread(); /* Get a file, read only */ 128 int filevisit(); /* Get a file, read write */ 129 int filewrite(); /* Write a file */ 130 int fileunmodify(); /* Turn off buffer changed bits */ 131 int filesave(); /* Save current file */ 132 int filename(); /* Adjust file name */ 133 int getcol(); /* Get current column */ 134 int gotobol(); /* Move to start of line */ 135 int forwchar(); /* Move forward by characters */ 136 int gotoeol(); /* Move to end of line */ 137 int backchar(); /* Move backward by characters */ 138 int forwline(); /* Move forward by lines */ 139 int backline(); /* Move backward by lines */ 140 int forwpage(); /* Move forward by pages */ 141 int backpage(); /* Move backward by pages */ 142 int gotobob(); /* Move to start of buffer */ 143 int gotoeob(); /* Move to end of buffer */ 144 int gotoline(); /* Move to line number */ 145 int removemark(); /* Remove mark */ 146 int swapmark(); /* Swap "." and mark */ 147 int forwsearch(); /* Search forward */ 148 int backsearch(); /* Search backwards */ 149 int search_paren(); /* Toggle over parentheses */ 150 int listbuffers(); /* Display list of buffers */ 151 int usebuffer(); /* Switch a window to a buffer */ 152 int buffer_next(); /* Switch to next buffer */ 153 int killbuffer(); /* Make a buffer go away. */ 154 int word_wrap_line(); /* Word wrap current line */ 155 int word_select(); /* Select word */ 156 int word_back(); /* Backup by words */ 157 int word_forw(); /* Advance by words */ 158 int misc_upper(); /* Upper case word/region */ 159 int misc_lower(); /* Lower case word/region */ 160 int capword(); /* Initial capitalize word. */ 161 int delfword(); /* Delete forward word. */ 162 int delbword(); /* Delete backward word. */ 163 int spawncli(); /* Run CLI in a subjob. */ 164 int spawn(); /* Run a command in a subjob. */ 165 int spawn_filter(); /* Filter buffer through program */ 166 int spawn_pipe(); /* Run program and gather output */ 167 int quickexit(); /* low keystroke style exit. */ 168 int delwind(); /* Delete a window */ 169 int filemodify(); /* Write modified files */ 170 int normexit(); /* Write modified files and exit*/ 171 int replacestring(); /* Search and replace */ 172 int queryreplacestring(); /* Query search and replace */ 173 int win32toggle43(); /* Toggle 43 line mode */ 174 int ibmpctoggle43(); /* Toggle 43 line mode */ 175 int display_norm_fg(); 176 int display_norm_bg(); 177 int display_mode_fg(); 178 int display_mode_bg(); 179 int display_mark_fg(); 180 int display_mark_bg(); 181 int display_eol_bg(); 182 int Dignore(); /* do nothing */ 183 int Dsearch(); /* Search */ 184 int Dsearchagain(); /* Search for the same string */ 185 int Ddelline(); /* Delete a line */ 186 int Dundelline(); /* Undelete a line */ 187 int Ddelword(); /* Delete a word */ 188 int Ddelbword(); /* Delete a word (backwards) */ 189 int Dundelword(); /* Undelete a word */ 190 int Dadvance(); /* Set into advance mode */ 191 int Dbackup(); /* Set into backup mode */ 192 int Dpause(); /* Pause the program (UNIX only)*/ 193 int Dinsertdate(); /* File and date stamp */ 194 int Dcppcomment(); /* convert to // comment */ 195 int Dinsertfile(); /* Insert a file */ 196 +/ 197 198 /* 199 * Command table. 200 * This table is *roughly* in ASCII order, left to right across the 201 * characters of the command. This expains the funny location of the 202 * control-X commands. 203 */ 204 205 enum CMD_ENDMACRO = 0x8005; 206 207 struct KEYTAB { 208 int k_code; /* Key code */ 209 int function(bool, int) k_fp; /* Routine to handle it */ 210 } 211 212 immutable KEYTAB[] keytab = 213 [ 214 /* Definitions common to all versions */ 215 { CTRL('@'), &ctrlg}, /*basic_setmark*/ 216 { CTRL('A'), &gotobol}, 217 { CTRL('B'), &backchar}, 218 { CTRL('C'), &quit}, 219 { CTRL('D'), &random_forwdel}, 220 { CTRL('E'), &gotoeol}, 221 { CTRL('F'), &forwchar}, 222 { CTRL('G'), &ctrlg}, 223 { CTRL('H'), &random_backdel}, 224 { CTRL('I'), &random_tab}, 225 { CTRL('J'), &Ddelline}, 226 { CTRL('K'), &random_kill}, 227 { CTRL('L'), &window_refresh}, 228 { CTRL('M'), &random_newline}, 229 { CTRL('N'), &forwline}, 230 { CTRL('O'), &random_openline}, 231 { CTRL('P'), &backline}, 232 { CTRL('Q'), &random_quote}, /* Often unreachable */ 233 { CTRL('R'), &backsearch}, 234 { CTRL('S'), &forwsearch}, /* Often unreachable */ 235 { CTRL('T'), &random_twiddle}, 236 { CTRL('V'), &forwpage}, 237 { CTRL('W'), &search_paren}, 238 { CTRL('Y'), &random_yank}, 239 { 0x7F, &random_backdel}, 240 /+ 241 /* Unused definitions from original microEMACS */ 242 { CTRL('C'), &spawncli}, /* Run CLI in subjob. */ 243 { CTRL('J'), &random_indent}, 244 { CTRL('W'), ®ion_kill}, 245 { CTRL('Z'), &quickexit}, /* quick save and exit */ 246 +/ 247 { CTRL('Z'), &spawncli}, /* Run CLI in subjob. */ 248 { F2KEY, &Dsearchagain}, 249 { F3KEY, &search_paren}, 250 { F4KEY, &Dsearch}, 251 { F5KEY, &basic_nextline}, 252 { F6KEY, &window_next}, 253 { F7KEY, &basic_setmark}, 254 { F8KEY, ®ion_copy}, 255 { F9KEY, ®ion_kill}, 256 { F10KEY, &random_yank}, 257 {F11KEY, &ctlxe}, 258 {F12KEY, ¯otoggle}, 259 {AltF1KEY, &display_norm_bg}, 260 {AltF2KEY, &display_norm_fg}, 261 {AltF3KEY, &display_mode_bg}, 262 {AltF5KEY, &display_mark_fg}, 263 {AltF6KEY, &display_mark_bg}, 264 {AltF4KEY, &display_mode_fg}, 265 {AltF7KEY, &display_eol_bg}, 266 {AltF9KEY, &random_decindent}, 267 {AltF10KEY, &random_incindent}, 268 {ALTB, &buffer_next}, 269 {ALTC, &main_saveconfig}, 270 {ALTX, &normexit}, 271 {ALTZ, &spawn_pipe}, 272 {RTKEY, &forwchar}, 273 {LTKEY, &backchar}, 274 {DNKEY, &forwline}, 275 {UPKEY, &backline}, 276 {InsKEY, &toggleinsert}, 277 {DelKEY, &random_forwdel}, 278 {PgUpKEY, &backpage}, 279 {PgDnKEY, &forwpage}, 280 {HOMEKEY, &window_mvup}, 281 {ENDKEY, &window_mvdn}, 282 {CtrlRTKEY, &word_forw}, 283 {CtrlLFKEY, &word_back}, 284 {CtrlHome, &gotobob}, 285 {CtrlEnd, &gotoeob}, 286 287 /* Commands with a special key value */ 288 {0x8001, &spawn_pipe}, 289 {0x8002, &spawn_filter}, 290 {0x8003, &random_showcpos}, 291 {0x8004, &ctlxlp}, 292 {CMD_ENDMACRO, &ctlxrp}, 293 {0x8006, &random_decindent}, 294 {0x8007, &random_incindent}, 295 {0x8008, &window_only}, 296 {0x8009, &removemark}, 297 {0x800A, &spawn.spawn}, /* Run 1 command. */ 298 {0x800B, &window_split}, 299 {0x800C, &usebuffer}, 300 {0x800D, &delwind}, 301 {0x800E, &ctlxe}, 302 {0x800F, &random_setfillcol}, 303 {0x8010, &buffer.killbuffer}, 304 {0x8011, &window_next}, 305 {0x8012, &window_prev}, 306 {0x8013, &random_quote}, 307 {0x8014, &buffer_next}, 308 {0x8015, &window_enlarge}, 309 {0x8016, &listbuffers}, 310 {0x8017, &filename}, 311 {0x8018, &filemodify}, 312 {0x8019, &window_mvdn}, 313 {0x801A, &random_deblank}, 314 {0x801B, &window_mvup}, 315 {0x801C, &fileread}, 316 {0x801D, &filesave}, /* Often unreachable */ 317 {0x801E, &window_reposition}, 318 {0x801F, &filevisit}, 319 {0x8020, &filewrite}, 320 {0x8021, &swapmark}, 321 {0x8022, &window_shrink}, 322 323 {0x8023, &delbword}, 324 {0x8024, &random_opttab}, 325 {0x8025, &basic_setmark}, 326 {0x8026, &gotoeob}, 327 {0x8027, &gotobob}, 328 {0x8028, ®ion_copy}, 329 {0x8029, ®ion_kill}, 330 {0x802A, &word_back}, 331 {0x802B, &capword}, 332 {0x802C, &delfword}, 333 {0x802D, &word_forw}, 334 {0x802E, &misc_lower}, 335 {0x802F, &queryreplacestring}, 336 {0x8030, &replacestring}, 337 {0x8031, &misc_upper}, 338 {0x8032, &backpage}, 339 {0x8033, &word_select}, 340 {0x8034, &Dadvance}, 341 {0x8035, &Dbackup}, 342 {0x8036, &random_deblank}, 343 344 {0x8037, &Dinsertdate}, 345 {0x8038, &Dinsertfile}, 346 {0x8039, &gotoline}, 347 {0x803A, &fileunmodify}, 348 {0x803B, &filenext}, 349 {0x803C, &quit}, 350 {0x803D, &normexit}, 351 {0x803E, &Dundelline}, 352 {0x803F, &Dsearch}, 353 {0x8040, &Dundelword}, 354 {0x8041, &random_undelchar}, 355 {0x8042, &random_openline}, 356 {0x8043, &random_kill}, 357 {0x8044, ®ion_togglemode}, 358 {0x8045, &Dcppcomment}, 359 {0x8046, &random_hardtab}, 360 {0x8047, &word_wrap_line}, 361 {0x8048, &help}, 362 {0x8049, &openBrowser}, 363 {0x804A, &scrollUnicode}, 364 ]; 365 366 /* Translation table from 2 key sequence to single value */ 367 immutable ushort[2][] altf_tab = 368 [ 369 ['B', 0x8016], /* listbuffers */ 370 ['D', 0x8037], /* Dinsertdate */ 371 ['F', 0x8017], /* filename */ 372 ['I', 0x8038], /* Dinsertfile */ 373 ['M', 0x8018], /* filemodify */ 374 ['N', 0x803B], /* filenext */ 375 ['Q', 0x803C], /* quit */ 376 ['R', 0x801C], /* fileread */ 377 ['S', 0x801D], /* filesave */ 378 ['T', 0x8046], // random_hardtab 379 ['U', 0x803A], /* fileunmodify */ 380 ['V', 0x801F], /* filevisit */ 381 ['W', 0x8020], /* filewrite */ 382 ['X', 0x803D], /* normexit */ 383 [F2KEY, 0x803E], /* Dundelline */ 384 [F4KEY, 0x803F], /* Dsearch */ 385 [CtrlRTKEY, 0x8040], /* Dundelword */ 386 [CtrlLFKEY, 0x8040], /* Dundelword */ 387 [DelKEY, 0x8041], /* random_undelchar */ 388 [InsKEY, 0x8042], /* random_openline */ 389 ]; 390 391 immutable ushort[2][] esc_tab = 392 [ 393 ['.', 0x8025], /* basic_setmark */ 394 ['>', 0x8026], /* gotoeob */ 395 [ENDKEY, 0x8026], /* gotoeob */ 396 ['<', 0x8027], /* gotobob */ 397 [HOMEKEY, 0x8027], /* gotobob */ 398 ['8', 0x8028], /* region_copy */ 399 ['9', 0x8029], /* region_kill */ 400 ['B', 0x802A], /* word_back */ 401 ['C', 0x802B], /* capword */ 402 ['D', 0x802C], /* delfword */ 403 ['E', 0x8049], // openBrowser 404 ['F', 0x802D], /* word_forw */ 405 ['H', 0x8023], /* delbword */ 406 ['I', 0x8024], /* random_opttab */ 407 ['J', 0x803E], // Dundelline 408 ['L', 0x802E], /* misc_lower */ 409 ['M', 0x8048], // help 410 ['N', 0x8019], /* window_mvdn */ 411 ['P', 0x801B], /* window_mvup */ 412 ['Q', 0x802F], /* queryreplacestring */ 413 ['R', 0x8030], /* replacestring */ 414 ['T', 0x8044], /* region_togglemode */ 415 ['U', 0x8031], /* misc_upper */ 416 ['V', 0x8032], /* backpage */ 417 ['W', 0x8033], /* word_select */ 418 ['X', 0x8021], /* swapmark */ 419 ['Z', 0x8022], /* window_shrink */ 420 [DNKEY, 0x8034], // Dadvance 421 [UPKEY, 0x8035], // Dbackup 422 ]; 423 424 immutable ushort[2][] ctlx_tab = 425 [ 426 ['@', 0x8001], // spawn_pipe 427 ['#', 0x8002], // spawn_filter 428 ['=', 0x8003], // random_showcpos 429 ['(', 0x8004], // ctlxlp 430 [')', 0x8005], // ctlxrp 431 ['[', 0x8006], // random_decindent 432 [']', 0x8007], // random_incindent 433 ['.', 0x8009], // removemark 434 ['!', 0x800A], // spawn 435 ['1', 0x8008], // window_only 436 ['2', 0x800B], // window_split 437 ['A', 0x8047], // word_wrap_line 438 ['B', 0x800C], // usebuffer 439 ['D', 0x800D], // delwind 440 ['E', 0x800E], // ctlxe 441 ['F', 0x800F], // random_setfillcol 442 ['K', 0x8010], // killbuffer 443 ['L', 0x8039], // gotoline 444 ['N', 0x8011], // window_next 445 ['O', 0x801A], // random_deblank 446 ['P', 0x8012], // window_prev 447 ['Q', 0x8013], // random_quote 448 ['T', 0x801E], // window_reposition 449 ['U', 0x804A], // scrollUnicode 450 ['W', 0x8014], // buffer_next 451 ['Z', 0x8015], // window_enlarge 452 ['/', 0x8045], // Dcppcomment 453 ]; 454 455 struct CMDTAB 456 { ushort ktprefix; /* prefix key value */ 457 immutable ushort[2][] kt; /* which translation table */ 458 }; 459 460 CMDTAB[3] cmdtab = 461 [ 462 { CTLX, ctlx_tab }, 463 { META, esc_tab }, 464 { GOLD, altf_tab }, 465 ]; 466 467 468 string[] gargs; 469 int gargi; 470 471 private int c; 472 473 int main(string[] args) 474 { 475 bool f; 476 int n; 477 string bname; 478 479 hasmouse = msm_init(); /* initialize mouse */ 480 progname = args[0]; /* remember program name */ 481 bname = "main"; /* Work out the name of */ 482 if (args.length > 1) /* the default buffer. */ 483 bname = makename(args[1]); 484 vtinit(); /* Displays. */ 485 edinit(bname); /* Buffers, windows. */ 486 if (args.length > 1) { 487 update(); /* You have to update */ 488 readin(args[1]); /* in case "[New file]" */ 489 } 490 else 491 mlwrite("[No file]"); 492 gargi = 2; 493 gargs = args; 494 lastflag = 0; /* Fake last flags. */ 495 while (1) 496 { 497 update(); /* Fix up the screen */ 498 c = getkey(); 499 if (mpresf != FALSE) /* if there is stuff in message line */ 500 { mlerase(); /* erase it */ 501 update(); 502 } 503 f = FALSE; 504 n = 1; 505 if (c == CTRL('U')) /* ^U, start argument */ 506 { f = TRUE; 507 n = getarg(); 508 } 509 if (kbdmip != null) { /* Save macro strokes. */ 510 if (c!=CMD_ENDMACRO && kbdmip>&kbdm[$-6]) { 511 ctrlg(FALSE, 0); 512 continue; 513 } 514 if (f != FALSE) { 515 *kbdmip++ = CTRL('U'); 516 *kbdmip++ = n; 517 } 518 *kbdmip++ = c; 519 } 520 execute(0, c, f, n); /* Do it. */ 521 } 522 return 0; 523 } 524 525 /****************************** 526 * Get and return numeric argument. 527 */ 528 529 int getarg() 530 { 531 int n; 532 int mflag; 533 534 n = 4; /* with argument of 4 */ 535 mflag = 0; /* that can be discarded. */ 536 mlwrite("Arg: 4"); 537 while ((c=getkey()) >='0' && c<='9' || c==CTRL('U') || c=='-'){ 538 if (c == CTRL('U')) 539 n = n*4; 540 /* 541 * If dash, and start of argument string, set arg. 542 * to -1. Otherwise, insert it. 543 */ 544 else if (c == '-') { 545 if (mflag) 546 break; 547 n = 0; 548 mflag = -1; 549 } 550 /* 551 * If first digit entered, replace previous argument 552 * with digit and set sign. Otherwise, append to arg. 553 */ 554 else { 555 if (!mflag) { 556 n = 0; 557 mflag = 1; 558 } 559 n = 10*n + c - '0'; 560 } 561 mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1)); 562 } 563 /* 564 * Make arguments preceded by a minus sign negative and change 565 * the special argument "^U -" to an effective "^U -1". 566 */ 567 if (mflag == -1) { 568 if (n == 0) 569 n++; 570 n = -n; 571 } 572 return n; 573 } 574 575 /* 576 * Initialize all of the buffers and windows. The buffer name is passed down 577 * as an argument, because the main routine may have been told to read in a 578 * file by default, and we want the buffer name to be right. 579 */ 580 void edinit(string bname) 581 { 582 auto bp = buffer_find(bname, TRUE, 0); /* First buffer */ 583 blistp = buffer_find("[List]", TRUE, BFTEMP); /* Buffer list buffer */ 584 auto wp = new WINDOW; // First window 585 if (bp==null || wp==null || blistp==null) 586 { vttidy(); 587 exit(1); 588 } 589 bp.b_nwnd = 1; /* Displayed. */ 590 curbp = bp; /* Make this current */ 591 windows ~= wp; 592 curwp = wp; 593 wp.w_bufp = bp; 594 wp.w_linep = bp.b_linep; 595 wp.w_dotp = bp.b_linep; 596 wp.w_ntrows = term.t_nrow-2; /* -1 for mode line, -1 for minibuffer */ 597 wp.w_flag = WFMODE|WFHARD; /* Full. */ 598 } 599 600 /* 601 * This is the general command execution routine. It handles the fake binding 602 * of all the keys to "self-insert". It also clears out the "thisflag" word, 603 * and arranges to move it to the "lastflag", so that the next command can 604 * look at it. Return the status of command. 605 */ 606 int execute(int prefix, int c, bool f, int n) 607 { 608 int status; 609 610 /* Look in key table. */ 611 foreach (ktp; keytab) 612 { if (ktp.k_code == c) 613 { thisflag = 0; 614 status = (*ktp.k_fp)(f, n); 615 lastflag = thisflag; 616 return (status); 617 } 618 } 619 620 /* 621 * If a space was typed, fill column is defined, the argument is non- 622 * negative, and we are now past fill column, perform word wrap. 623 */ 624 if (c == ' ' && fillcol > 0 && n>=0 && 625 getcol(curwp.w_dotp,curwp.w_doto) > fillcol) 626 word_wrap(false, 0); 627 628 if ((c>=0x20 && c<=0x7E) /* Self inserting. */ 629 || (c>=0xA0 && c<=0xFE)) { 630 if (n <= 0) { /* Fenceposts. */ 631 lastflag = 0; 632 return (n<0 ? FALSE : TRUE); 633 } 634 thisflag = 0; /* For the future. */ 635 status = insertmode ? line_insert(n, cast(char)c) : line_overwrite(n, cast(char)c); 636 lastflag = thisflag; 637 return (status); 638 } 639 640 /* 641 * Beep if an illegal key is typed 642 */ 643 term.t_beep(); 644 lastflag = 0; /* Fake last flags. */ 645 return (FALSE); 646 } 647 648 /* 649 * Read in a key. 650 * Do the standard keyboard preprocessing. Convert the keys to the internal 651 * character set. 652 */ 653 int getkey() 654 { 655 int c; 656 657 ttyield(); 658 while (hasmouse && !ttkeysininput()) 659 { c = mouse_command(); 660 if (c) 661 return c; 662 ttyield(); 663 ttwaitkeys(); 664 } 665 c = term.t_getchar(); 666 switch (c) 667 { 668 /+ 669 case MENU_BUTTON: 670 c = memenu_button(); 671 break; 672 +/ 673 case META: 674 case GOLD: 675 case CTLX: 676 c = get2nd(c); 677 break; 678 679 default: 680 break; 681 } 682 683 return (c); 684 } 685 686 /************************ 687 * Get second key of two key command. 688 * Input: 689 * the first key value 690 */ 691 692 static int get2nd(int flag) 693 { 694 int c; 695 int i,j; 696 697 /+ 698 auto starttime = clock(); 699 while (!ttkeysininput()) 700 if (clock() > starttime + CLK_TCK) 701 { switch (flag) 702 { case CTLX: 703 return cast(ushort) memenu_ctlx(1,disp_cursorrow,disp_cursorcol); 704 case GOLD: 705 return cast(ushort) memenu_gold(1,disp_cursorrow,disp_cursorcol); 706 case META: 707 return cast(ushort) memenu_meta(1,disp_cursorrow,disp_cursorcol); 708 } 709 } 710 +/ 711 c = term.t_getchar(); 712 713 /* Treat control characters and lowercase the same as upper case */ 714 if (c>='a' && c<='z') /* Force to upper */ 715 c -= 0x20; 716 else if (c >= CTRL('A') && c <= CTRL('Z')) 717 c += 0x40; 718 719 /* Translate to special keycode */ 720 for (i = 0; 1; i++) 721 if (cmdtab[i].ktprefix == flag) 722 break; 723 for (j = 0; 1; j++) 724 { 725 if (j == cmdtab[i].kt.length) 726 { c = 0; 727 break; 728 } 729 if (cmdtab[i].kt[j][0] == c) 730 { c = cmdtab[i].kt[j][1]; 731 break; 732 } 733 } 734 return c; 735 } 736 737 /* 738 * An even better exit command. Writes all modified files and then 739 * exits. 740 */ 741 int normexit(bool f, int n) 742 { 743 filemodify(f, n); // write all modified files 744 update(); // make the screen look nice 745 quit(f, n); 746 return false; 747 } 748 749 /* 750 * Quit command. If an argument, always quit. Otherwise confirm if a buffer 751 * has been changed and not written out. Normally bound to "C-X C-C". 752 */ 753 int quit(bool f, int n) 754 { 755 if (f != FALSE /* Argument forces it. */ 756 || anycb() == FALSE /* All buffers clean. */ 757 || (mlyesno("Quit [y/n]? "))) /* User says it's OK. */ 758 { vttidy(); 759 exit(0); 760 } 761 return FALSE; 762 } 763 764 /* 765 * Begin a keyboard macro. 766 * Error if not at the top level in keyboard processing. Set up variables and 767 * return. 768 */ 769 int ctlxlp(bool f, int n) 770 { 771 if (kbdmip!=null) { 772 mlwrite("Not now: recording"); 773 return (FALSE); 774 } 775 if (kbdmop!=null) { 776 mlwrite("Not now: executing"); 777 return (FALSE); 778 } 779 mlwrite("[Start macro]"); 780 kbdmip = kbdm.ptr; 781 782 foreach (wp; windows) 783 wp.w_flag |= WFMODE; /* so highlighting is updated */ 784 785 return (TRUE); 786 } 787 788 /* 789 * End keyboard macro. Check for the same limit conditions as the above 790 * routine. Set up the variables and return to the caller. 791 */ 792 int ctlxrp(bool f, int n) 793 { 794 if (kbdmip == null) { 795 mlwrite("Not recording"); 796 return (FALSE); 797 } 798 mlwrite("[End macro]"); 799 kbdmip = null; 800 801 foreach (wp; windows) 802 wp.w_flag |= WFMODE; /* so highlighting is updated */ 803 804 return (TRUE); 805 } 806 807 /* 808 * If in a macro 809 * end macro 810 * Else 811 * start macro 812 */ 813 814 int macrotoggle(bool f, int n) 815 { 816 if (kbdmip) 817 return ctlxrp(f, n); 818 else 819 return ctlxlp(f, n); 820 } 821 822 /* 823 * Execute a macro. 824 * The command argument is the number of times to loop. Quit as soon as a 825 * command gets an error. Return TRUE if all ok, else FALSE. 826 */ 827 int ctlxe(bool f, int n) 828 { 829 int c; 830 bool af; 831 int an; 832 int s; 833 834 if (kbdmip!=null || kbdmop!=null) { 835 /* Can't execute macro if defining a macro or if */ 836 /* in the middle of executing one. */ 837 mlwrite("Not now"); 838 return (FALSE); 839 } 840 if (n <= 0) 841 /* Execute macro 0 or fewer (!) times */ 842 return (TRUE); 843 do { 844 kbdmop = &kbdm[0]; 845 do { 846 af = FALSE; 847 an = 1; 848 if ((c = *kbdmop++) == CTRL('U')) { 849 af = TRUE; 850 an = *kbdmop++; 851 c = *kbdmop++; 852 } 853 s = TRUE; 854 } while (c!=CMD_ENDMACRO && (s=execute(0, c, af, an))==TRUE); 855 kbdmop = null; 856 } while (s==TRUE && --n); 857 return (s); 858 } 859 860 /* 861 * Abort. 862 * Beep the beeper. Kill off any keyboard macro, etc., that is in progress. 863 * Sometimes called as a routine, to do general aborting of stuff. 864 */ 865 int ctrlg(bool f, int n) 866 { 867 term.t_beep(); 868 if (kbdmip != null) { 869 kbdm[0] = CMD_ENDMACRO; 870 kbdmip = null; 871 } 872 return ABORT; 873 } 874 875 version (Windows) 876 { 877 CONFIG config = 878 { // mode, norm, eol, mark, tab, url, search 879 //0x74,0x02,0x07,0x24, 880 //0x34,0x7F,0x78,0x3B, 881 //0x34,0x0E,0x0E,0x3B, 882 //0x34,0x70,0x70,0x3B, 883 //0x34,0xF0,0xF0,0x3B, 884 0x3E,0xF0,0xF0,0x3B, 885 ' '/*0xAF*/, 886 0xF9, // url 887 0xE1, // search 888 889 0xF9, //0xF3, // keyword 890 0xFC, //0xF4, // string 891 0xF8, //0xF2, // comment 892 }; 893 } 894 else version (Posix) 895 { 896 CONFIG config = 897 { 898 Color.bgCyan | Color.lightYellow, // mode 899 Color.black, // norm 900 Color.black, // eol 901 Color.reverse, // mark 902 ' ', // tab 903 Color.underline | Color.blue, // url 904 Color.bgYellow | Color.black, // search 905 906 Color.blue, // keyword 907 Color.red, // string 908 Color.magenta, // comment 909 }; 910 } 911 else 912 { 913 CONFIG config = 914 { 915 Color.bright, // mode 916 0, // norm 917 0, // eol 918 Color.bright, // mark 919 ' ', // tab 920 0, // url 921 Color.yellow, // search 922 0, // keyword 923 0, // string 924 0, // comment 925 }; 926 } 927 928 929 /******************************** 930 * Save configuration. 931 */ 932 933 int main_saveconfig(bool f, int n) 934 { 935 return FALSE; 936 } 937 938 int toggleinsert(bool f, int n) 939 { 940 insertmode ^= 1; 941 term.t_setcursor(insertmode); 942 return true; 943 } 944