void write_admin_menu(int shift) {
	int i;

	// The options available
	const char *options[] = {
		"1. Restock",
		"2. Enroll",
		"3. Deal Drugs",
		"0. Exit"
	};
	const int num_options = 4; // Should be the number of things in the above

	// Don't let us shift more than the number of options
	if (shift > num_options) {
		return;
	}

	// Whealer's fault. Shift options around in a circle
	admin_line += shift + num_options;
	admin_line %= num_options;

	// Clean up
	clear_screen();
	cursor_blink_off();
	cursor_off();

	// Write the first thing
	write_string(options[admin_line]);

	// Write the next thing - go around in a circle. Also Whealer's fault
	write_string("\n");
	write_string(options[(admin_line + 1) % num_options]);
}
Example #2
0
int main()
{
	char insert_key;

	clrscr();
	Outside_Box();
	Inside_Box();
	cursor_off();

	while(1)
	{
		press_key = getch();
		insert_key = check_key_value(press_key);	
		switch(insert_key)
		{
		case F10:
			move_inverse();
			break;
		case F1:
			print_string(9, 9, "Help", 7);
			break;
		case ALTL:
			print_string(9, 9, "Load", 7);
			break;
		case ALTS:
			print_string(9, 9, "Save", 7);
			break;
		case ALTA:
			print_string(9, 9, "Save as", 7);
			break;
		case ALTX:
			return 0;
		}
	}
}
Example #3
0
void message(char *s) {
    cursor_off();
    clear_screen();
    cursor(10, 10);
    printf("%s", s);
    getch();
    cursor_on();
}
Example #4
0
void LCDi2cR::init () {
	
	I2c.begin();
	
	on();
	clear();
	blink_off();
	cursor_off(); 
	home();
	
}
Example #5
0
bool LCDi2cNHD::init () {
        
        Wire.begin();
        // TODO: Check that LCD was initialized properly. on() should return a value, command() should return a value and check endTranmission value, a global flag (initializeError) should be added
        if ( !on() )
        {
                return false;  // error
        }
        
        clear();
        blink_off();
        cursor_off(); 
        home();
        
        return true; // success
}
Example #6
0
//print the matrix
void print_matrix(void){
	char p,l;
	
	fill();
	cursor_off();
	print_hits();

	l = 20-(players<<1);
	print_num(level,2,36,l);
	for (p=0;p<players+1;++p){
		l += 2;
		print_num(score[p],6,28,l);
	}
	stop = 1;	
	display_time();
	appear();
	cursor_on();
	delay(230);
}
Example #7
0
static void xorcursor()
{
    static byte store_x,store_lh;
    static unsigned store_lhb;
    static byte state=0;
    extern byte display_x;
    store_x=display_x;
    store_lh=line_height;
    store_lhb=line_height_bytes;
    display_x=x;
    cursor_y=y1;
    line_height=ozgetfontheight(ozgetfont());
    line_height_bytes=30*line_height;
    if(state^=1)
        do_cursor_on();
    else
        cursor_off();
    display_x=store_x;
    line_height=store_lh;
    line_height_bytes=store_lhb;
}
Example #8
0
File: devtty.c Project: 8l/FUZIX
void tty_putc(uint8_t minor, unsigned char c)
{
    irqflags_t irq;
    if (minor == 3)
        tr1865_rxtx = c;
    else {
        irq = di();
        if (curtty != minor -1) {
            /* Kill the cursor as we are changing the memory buffers. If
               we don't do this the next cursor_off will hit the wrong
               buffer */
            cursor_off();
            vt_save(&ttysave[curtty]);
            curtty = minor - 1;
            vt_load(&ttysave[curtty]);
            /* Fix up the cursor */
            cursor_on(ttysave[curtty].cursory, ttysave[curtty].cursorx);
       }
       vtoutput(&c, 1);
       irqrestore(irq);
   }
}
Example #9
0
File: devtty.c Project: 8l/FUZIX
void vtexchange(void)
{
        /* Swap the pointers over: TRS80 video we switch by copying not
           flipping hardware pointers */
        uint8_t *v = vtbase[0];
        vtbase[0] = vtbase[1];
        vtbase[1] = v;
        /* The cursor x/y for current tty are stale in the save area
           so save them */
        vt_save(&ttysave[curtty]);

        /* Before we flip the memory */
        cursor_off();

        /* Swap the buffers over */
        __asm
                ld hl, #0xf800
                ld de, #_vtbackbuf
                ld bc, #VT_WIDTH*VT_HEIGHT
        exchit:
                push bc
                ld a, (de)	; Could be optimised but its only 2K
                ld c, (hl)	; Probably worth doing eventuallly
                ex de, hl
                ld (hl), c
                ld (de), a
                inc hl
                inc de
                pop bc
                dec bc
                ld a, b
                or c
                jr nz, exchit
                ret
        __endasm;
        /* Cursor back */
        cursor_on(ttysave[inputtty].cursory, ttysave[inputtty].cursorx);
}
Example #10
0
File: vt.c Project: Rappalot/FUZIX
/* VT52 alike functionality */
void vtoutput(unsigned char *p, unsigned int len)
{
	irqflags_t irq;
	uint8_t cq;

	/* We can get re-entry into the vt code from tty echo. This is one of
	   the few places in Fuzix interrupts bite us this way.

	   If we have a clash then we queue the echoed symbol and print it
	   in the thread of execution it interrupted. We only queue one so
	   in theory might lose the odd echo - but the same occurs with real
	   uarts. If anyone actually has printing code slow enough this is a
	   problem then vtpend can turn into a small queue */
	irq = di();
	if (vtbusy) {
		vtpend = *p;
		irqrestore(irq);
		return;
	}
	vtbusy = 1;
	irqrestore(irq);
	cursor_off();
	do {
		while (len--) {
			unsigned char c = *p++;
			if (vtmode == 0) {
				charout(c);
				continue;
			}
			if (vtmode == 1) {
				vtmode = escout(c);
				continue;
			}
			if (vtmode == 2) {
				ncursory = c - ' ';
				vtmode++;
				continue;
			} else if (vtmode == 3) {
				int ncursorx = c - ' ';
				if (ncursory >= 0 && ncursorx <= VT_BOTTOM)
					cursory = ncursory;
				if (ncursorx >= 0 && ncursorx <= VT_RIGHT)
					cursorx = ncursorx;
					vtmode = 0;
			} else {
				vtattr = c;
				vtmode = 0;
				continue;
			}
		}
		/* Copy the pending symbol and clear the buffer */
		cq = vtpend;
		vtpend = 0;
		/* Any loops print the single byte in cq */
		p = &cq;
		len = 1;
		/* Until we don't get interrupted */
	} while(cq);

	cursor_on(cursory, cursorx);
	vtbusy = 0;
}
Example #11
0
int intake(struct world *mzx_world, char *string, int max_len,
 int x, int y, char color, int exit_type, int filter_type,
 int *return_x_pos, bool robo_intk, char *macro)
{
  int currx, curr_len, macro_position = -1;
  int done = 0, place = 0;
  char cur_char = 0;
  char temp_char;
  int in_macro;
  int use_mask = mzx_world->conf.mask_midchars;
  int mouse_press;
  int key;

  if(macro != NULL)
    macro_position = 0;

  // Activate cursor
  if(insert_on)
    cursor_underline();
  else
    cursor_solid();
  // Put cursor at the end of the string...
  currx = curr_len = (int)strlen(string);

  // ...unless return_x_pos says not to.
  if((return_x_pos) && (*return_x_pos < currx))
    currx = *return_x_pos;

  if(robo_intk && (currx > 75))
    move_cursor(77, y);
  else
    move_cursor(x + currx, y);

  if(insert_on)
    cursor_underline();
  else
    cursor_solid();

  do
  {
    if(!robo_intk)
    {
      if(use_mask)
        write_string_mask(string, x, y, color, 0);
      else
        write_string_ext(string, x, y, color, 0, 0, 16);
    }
    else
    {
      draw_char('\x11', color, 79, y);
      if((curr_len < 76) || (currx < 76))
      {
        draw_char('\x10', color, 0, y);

        if(curr_len < 76)
        {
          if(use_mask)
            write_line_mask(string, x, y, color, 0);
          else
            write_line_ext(string, x, y, color, 0, 0, 16);
          fill_line(76 - curr_len, x + curr_len, y, 32, color);
        }
        else
        {
          temp_char = string[76];
          string[76] = 0;
          if(use_mask)
            write_line_mask(string, x, y, color, 0);
          else
            write_line_ext(string, x, y, color, 0, 0, 16);
          string[76] = temp_char;

          draw_char('\xaf', color, 79, y);
        }
      }
      else
      {
        draw_char('\x20', color, 77, y);
        if(strlen(string + currx - 75) > 78)
        {
          temp_char = string[currx + 1];
          string[currx + 1] = 0;
          if(use_mask)
          {
            write_line_mask(string + currx - 75, x, y, color, 0);
          }
          else
          {
            write_line_ext(string + currx - 75, x, y,
             color, 0, 0, 16);
          }
          string[currx + 1] = temp_char;
        }
        else
        {
          if(use_mask)
          {
            write_line_mask(string + currx - 75, x, y, color, 0);
          }
          else
          {
            write_line_ext(string + currx - 75, x, y,
             color, 0, 0, 16);
          }
        }
        draw_char('\xae', color, 0, y);
        if(currx < curr_len)
          draw_char('\xaf', color, 79, y);
      }
      draw_char('\x20', color, 78, y);
    }

    if(!robo_intk)
    {
      fill_line(max_len + 1 - curr_len, x + curr_len, y, 32, color);
    }
    else
    {
      write_number(currx + 1, 79, 32, 0, 3, 0, 10);
      write_number(curr_len + 1, 79, 36, 0, 3, 0, 10);
    }

    in_macro = 0;

    // Get key
    if(macro_position != -1)
    {
      key = macro[macro_position];
      cur_char = key;

      macro_position++;
      if(macro[macro_position] == 0)
        macro_position = -1;

      if(key == '^')
        key = IKEY_RETURN;
    }
    else
    {
      update_screen();
      update_event_status_delay();
      key = get_key(keycode_internal);
      place = 0;

      cur_char = get_key(keycode_unicode);
    }

    mouse_press = get_mouse_press_ext();

    if(get_mouse_press_ext())
    {
      int mouse_x, mouse_y;
      get_mouse_position(&mouse_x, &mouse_y);
      if((mouse_y == y) && (mouse_x >= x) &&
       (mouse_x <= (x + max_len)) && (mouse_press <= MOUSE_BUTTON_RIGHT))
      {
        // Yep, reposition cursor.
        currx = mouse_x - x;
        if(currx > curr_len)
          currx = curr_len;
      }
      else
      {
        key = -1;
        done = 1;
      }
    }

    // Handle key cases
    switch(key)
    {
      case IKEY_ESCAPE:
      {
        // ESC
        if(exit_type > 0)
        {
          done = 1;
        }
        break;
      }

      case IKEY_RETURN:
      {
        // Enter
        done = 1;
        break;
      }

      case IKEY_HOME:
      {
        if(get_alt_status(keycode_internal) && robo_intk)
        {
          done = 1;
        }
        else
        {
          // Home
          currx = 0;
        }
        break;
      }

      case IKEY_END:
      {
        if(get_alt_status(keycode_internal) && robo_intk)
        {
          done = 1;
        }
        else
        {
          // End
          currx = curr_len;
        }
        break;
      }

      case IKEY_LEFT:
      {
        if(get_ctrl_status(keycode_internal))
        {
          // Find nearest space to the left
          if(currx)
          {
            char *current_position = string + currx;

            if(currx)
              current_position--;

            if(!isalnum((int)*current_position))
            {
              while(currx && !isalnum((int)*current_position))
              {
                current_position--;
                currx--;
              }
            }

            do
            {
              current_position--;
              currx--;
            } while(currx && isalnum((int)*current_position));

            if(currx < 0)
              currx = 0;
          }
        }
        else
        {
          // Left
          if(currx > 0)
            currx--;
        }

        break;
      }

      case IKEY_RIGHT:
      {
        if(get_ctrl_status(keycode_internal))
        {
          // Find nearest space to the right
          if(currx < curr_len)
          {
            char *current_position = string + currx;
            char current_char = *current_position;
            if(!isalnum((int)current_char))
            {
              do
              {
                current_position++;
                currx++;
                current_char = *current_position;
              } while(current_char && !isalnum((int)current_char));
            }

            while(current_char && isalnum((int)current_char))
            {
              current_position++;
              currx++;
              current_char = *current_position;
            }
          }
        }
        else
        {
          // Right
          if(currx < curr_len)
            currx++;
        }

        break;
      }

      case IKEY_F1:
      case IKEY_F2:
      case IKEY_F3:
      case IKEY_F4:
      case IKEY_F5:
      case IKEY_F6:
      case IKEY_F7:
      case IKEY_F8:
      case IKEY_F9:
      case IKEY_F10:
      case IKEY_F11:
      case IKEY_F12:
      case IKEY_UP:
      case IKEY_DOWN:
      case IKEY_TAB:
      case IKEY_PAGEUP:
      case IKEY_PAGEDOWN:
      {
        done = 1;
        break;
      }

      case IKEY_INSERT:
      {
        if(get_alt_status(keycode_internal) && robo_intk)
        {
          done = 1;
        }
        else
        {
          // Insert
          if(insert_on)
            cursor_solid();
          else
            cursor_underline();

          insert_on ^= 1;
        }
        break;
      }

      case IKEY_BACKSPACE:
      {
        // Backspace, at 0 it might exit
        if(get_alt_status(keycode_internal))
        {
          // Alt-backspace, erase input
          curr_len = currx = 0;
          string[0] = 0;
        }
        else

        if(get_ctrl_status(keycode_internal))
        {
          // Find nearest space to the left
          if(currx)
          {
            int old_position = currx;

            if(!isalnum((int)string[currx]))
            {
              while(currx && !isalnum((int)string[currx]))
              {
                currx--;
              }
            }

            while(currx && isalnum((int)string[currx]))
            {
              currx--;
            }

            curr_len -= old_position - currx;

            memmove(string + currx, string + old_position,
             strlen(string + old_position) + 1);
          }
        }
        else

        if(currx == 0)
        {
          if(exit_type == 2)
          {
            done = 1;
          }
        }
        else
        {
          // Move all back 1, decreasing string length
          memmove(string + currx - 1, string + currx, curr_len - currx + 1);
          curr_len--;
          // Cursor back one
          currx--;
        }
        break;
      }

      case IKEY_DELETE:
      {
        // Delete, at the end might exit
        if(currx == curr_len)
        {
          if(exit_type == 2)
            done = 1;
        }
        else
        {
          if(curr_len)
          {
            // Move all back 1, decreasing string length
            memmove(string + currx, string + currx + 1, curr_len - currx);
            curr_len--;
          }
        }
        break;
      }

      case IKEY_c:
      {
        if(get_ctrl_status(keycode_internal) && robo_intk)
        {
          done = 1;
        }
        else

        if(get_alt_status(keycode_internal) && !filter_type)
        {
          // If alt - C is pressed, choose character
          int new_char = char_selection(last_char);
          if(new_char >= 32)
          {
            cur_char = new_char;
            last_char = new_char;
            place = 1;
          }
          else
          {
            place = 0;
          }
        }
        else
        {
          place = 1;
        }

        break;
      }

      case IKEY_t:
      {
        if(get_alt_status(keycode_internal))
        {
          done = 1;
        }
        else
        {
          place = 1;
        }
        break;
      }

      case IKEY_l:
      case IKEY_g:
      case IKEY_d:
      case IKEY_f:
      case IKEY_r:
      {
        if(get_ctrl_status(keycode_internal) && robo_intk)
        {
          done = 1;
        }
        else
        {
          place = 1;
        }
        break;
      }

      case IKEY_i:
      {
        if((get_ctrl_status(keycode_internal) ||
         get_alt_status(keycode_internal)) && robo_intk)
        {
          done = 1;
        }
        else
        {
          place = 1;
        }
        break;
      }

      case IKEY_u:
      case IKEY_o:
      case IKEY_x:
      case IKEY_b:
      case IKEY_s:
      case IKEY_e:
      case IKEY_v:
      case IKEY_p:
      case IKEY_h:
      case IKEY_m:
      {
        if(get_alt_status(keycode_internal) && robo_intk)
        {
          done = 1;
        }
        else
        {
          place = 1;
        }
        break;
      }

      case IKEY_LSHIFT:
      case IKEY_RSHIFT:
      case 0:
      {
        place = 0;
        break;
      }

      default:
      {
        // Place the char
        place = 1;
        break;
      }

      case -1:
      {
        break;
      }
    }

    if(place)
    {
      if((cur_char < 32) && (exit_type == 2))
      {
        done = 1;
        key = cur_char;
      }
      else

      // Keycode.. Filter.
      if(filter_type & 1)
      {
        if((cur_char >= 'a') && (cur_char <= 'z'))
          cur_char -= 32;
      }

      if(filter_type & 2)
      {
        if((cur_char >= 'A') && (cur_char <= 'Z'))
          cur_char += 32;
      }

      // Block numbers
      if((filter_type & 4) && ((cur_char >= '0') && (cur_char <= '9')))
      {
        place = 0;
      }

      // Block alpha
      if((filter_type & 8) &&
       (((cur_char >= 'a') && (cur_char <= 'z')) ||
       ((cur_char >= 'A') && (cur_char <= 'Z'))))
      {
        place = 0;
      }

      // Block spaces
      if((filter_type & 16) && (cur_char == ' '))
      {
        place = 0;
      }

      // Block high-ASCII
      if((filter_type & 32) && (cur_char > 126))
      {
        place = 0;
      }

      // Block these chars
      if((filter_type & 64) &&
       ((cur_char == '*') || (cur_char == '[') ||
       (cur_char == ']') || (cur_char == '>') ||
       (cur_char == '<') || (cur_char == ',') ||
       (cur_char == '|') || (cur_char == '?') ||
       (cur_char == '=') || (cur_char == ';') ||
       (cur_char == '\"') || (cur_char =='/')))
      {
        place = 0;
      }

      // Block these chars
      if((filter_type & 128) &&
       ((cur_char == ':') || (cur_char == '\\')))
      {
        place = 0;
      }

      // Block these chars
      if((filter_type & 256) &&
       (((cur_char > ' ') && (cur_char < '0')) ||
       ((cur_char > '9') && (cur_char < 'A')) ||
       ((cur_char > 'Z') && (cur_char < 'a')) ||
       ((cur_char > 'z') && (cur_char < 127))))
      {
        place = 0;
      }

      // Now, can it still be placed?
      if(place && (curr_len != max_len) && (!done) && cur_char)
      {
        // Overwrite or insert?
        if((insert_on) || (currx == curr_len))
        {
          // Insert- Move all ahead 1, increasing string length
          curr_len++;
          memmove(string + currx + 1, string + currx, curr_len - currx);
        }
        // Add character and move forward one
        string[currx++] = cur_char;
      }
    }

    // Move cursor
    if(robo_intk && (currx > 75))
      move_cursor(77, y);
    else
      move_cursor(x + currx, y);

    if(insert_on)
      cursor_underline();
    else
      cursor_solid();

    // Loop
  } while(!done);

  cursor_off();
  if(return_x_pos)
    *return_x_pos = currx;

  return key;
}
Example #12
0
int main(int argc, char **argv)
{
    float bitcoins = 25.0;
    if (argc > 1)
        bitcoins = atof(argv[1]);

    signal(SIGINT, sighandler);
    cursor_off();
    clear();

    float usd_btc_last = 0;
    float usd_btc = 0;
    do {
        float eur_in_usd = get_eur_in_usd();
        float usd_in_nok = get_usd_in_nok();

        if (argc > 2)
            usd_btc = atof(argv[2]);

        if (mtgox) {
            time_t btc_time = mtgox_time();
            struct tm *tm = localtime(&btc_time);

            char timebuf[16];
            sprintf(timebuf, "%02u:%02u:%02u", tm->tm_hour, tm->tm_min, tm->tm_sec);

            usd_btc = mtgox_usd();
            printf("\r%s%s%.04f%s$ #BTC: %.02f TOTAL: { %sUSD: %.02f, EUR: %.02f, NOK: %.02f%s } USD in NOK: %.04f, EXCHANGE SAMPLED: %s",
                COLOR_BOLD,
                usd_btc_last <= usd_btc ? COLOR_GREEN : COLOR_RED,
                usd_btc,
                COLOR_NORMAL,
                bitcoins,
                COLOR_BOLD,
                bitcoins * usd_btc,
                (bitcoins * usd_btc) / eur_in_usd,
                (bitcoins * usd_btc) * usd_in_nok,
                COLOR_NORMAL,
                usd_in_nok,
                timebuf
            );
        } else {
            usd_btc = bitcoin24_usd();
            printf("\r%s%s%.04f%s$ #BTC: %.02f TOTAL: { %sUSD: %.02f, EUR: %.02f, NOK: %.02f%s } USD in NOK: %.04f",
                COLOR_BOLD,
                usd_btc_last <= usd_btc ? COLOR_GREEN : COLOR_RED,
                usd_btc,
                COLOR_NORMAL,
                bitcoins,
                COLOR_BOLD,
                bitcoins * usd_btc,
                (bitcoins * usd_btc) / eur_in_usd,
                (bitcoins * usd_btc) * usd_in_nok,
                COLOR_NORMAL,
                usd_in_nok
            );
        }

        fflush(stdout);
        sleep(10);
        usd_btc_last = usd_btc;
    } while(1);
    cursor_on();

    return 0;
}
Example #13
0
void title_screen(void){
	char j,k,choice;

	while(1){
		stop = 1;
		players = team = demo = choice = tt = 0;
		init_msx(2);
		title_irq();
		cursor_off();
		memmove((char*)0xd800,(char*)(&bmp_data + LINES*40 + LINES*320),LINES*40);
//		memset((char*)0xcea8,0xff,40);
		fill();
		revers(1);
		textcolor(1); cputsxy(12,18,	"one player game");
		textcolor(2); cputsxy(12,19,	"two player team");
		textcolor(7); cputsxy(11,20,	"two player battle");
		textcolor(2); cputsxy(15,21,	"highscores");
//		textcolor(1); cputsxy(18,22,	"demo");

		while (!demo){
			do_bar(choice);
			j = *(char*)0xdc00;
			if (j == 111)
				break;
			
			if (j == 126){
				if (choice){
					for (k=0;k<8;++k){
						do_bar(--choice);
					}
				}
			}			
			else if (j == 125){
				if (choice < 24){
					for (k=0;k<8;++k){
						do_bar(++choice);
					}
				}
			}
		}
		if (demo)			
			break;
		choice>>=3;
		
		if (choice == 1){
			team = 1;
		}
		else if (choice == 2){
			players = 1;
		}
		else if (choice == 3){
			game_irq();
			show_highscores();
			continue;
		}
		break;
	}
	fld(17);
	while (!fld_done);
	game_irq();
//	gfx_mode();
	fill();
	*(char*)0xd016 = 0x10;
	delay (35);
	if (demo){
		txt_mode();
		print2x2_centered("demo mode",7,8,10);
		delay(255);
	}
}
Example #14
0
void help_system(struct world *mzx_world)
{
  char file[13], file2[13], label[13];
  int where, offs, size, t1, t2;
  enum cursor_mode_types old_cmode;
  FILE *fp;

  fp = mzx_world->help_file;
  if(!fp)
    return;

  old_cmode = get_cursor_mode();

  rewind(fp);
  t1 = fgetw(fp);
  fseek(fp, t1 * 21 + 4 + get_context() * 12, SEEK_SET);

  // At proper context info
  where = fgetd(fp);    // Where file to load is
  size = fgetd(fp);     // Size of file to load
  offs = fgetd(fp);     // Offset within file of link

  // Jump to file
  fseek(fp, where, SEEK_SET);
  // Read it in
  fread(help, 1, size, fp);
  // Display it
  cursor_off();

labelled:
  help_display(mzx_world, help, offs, file, label);

  // File?
  if(file[0])
  {
    // Yep. Search for file.
    fseek(fp, 2, SEEK_SET);
    for(t2 = 0; t2 < t1; t2++)
    {
      fread(file2, 1, 13, fp);
      if(!strcmp(file, file2))
        break;
      fseek(fp, 8, SEEK_CUR);
    }

    if(t2 < t1)
    {
      // Found file.
      where = fgetd(fp);
      size = fgetd(fp);
      fseek(fp, where, SEEK_SET);
      fread(help, 1, size, fp);

      // Search for label
      for(t2 = 0; t2 < size; t2++)
      {
        if(help[t2] != 255)
          continue;
        if(help[t2 + 1] != ':')
          continue;
        if(!strcmp(help + t2 + 3, label))
          break; // Found label!
      }

      if(t2 < size)
      {
        // Found label. t2 is offset.
        offs = t2;
        goto labelled;
      }
    }
  }

  set_cursor_mode(old_cmode);
}
Example #15
0
	void
normal()
{
	register int	c;
	long 			n;
	int				flag = FALSE;
	int				flag2 = FALSE;
	int 			type = 0;				/* type of operation */
	int 			dir = FORWARD;			/* search direction */
	int				nchar = NUL;
	int				finish_op;
	linenr_t		Prenum1;
	char_u			searchbuff[CMDBUFFSIZE];/* buffer for search string */
	FPOS			*pos = NULL;			/* init for gcc */
	register char_u	*ptr;
	int				command_busy = FALSE;
	static int		didwarn = FALSE;		/* warned for broken inversion */
	int				modified = FALSE;		/* changed current buffer */
	int				ctrl_w = FALSE;			/* got CTRL-W command */

		/* the visual area is remembered for reselection */
	static linenr_t	resel_Visual_nlines;		/* number of lines */
	static int		resel_Visual_type = 0;	/* type 'v', 'V' or CTRL-V */
	static colnr_t	resel_Visual_col;		/* number of columns or end column */
		/* the visual area is remembered for redo */
	static linenr_t	redo_Visual_nlines;		/* number of lines */
	static int		redo_Visual_type = 0;	/* type 'v', 'V' or CTRL-V */
	static colnr_t	redo_Visual_col;		/* number of columns or end column */
	static long		redo_Visual_Prenum;		/* Prenum for operator */

	Prenum = 0;
	/*
	 * If there is an operator pending, then the command we take this time
	 * will terminate it. Finish_op tells us to finish the operation before
	 * returning this time (unless the operation was cancelled).
	 */
	finish_op = (operator != NOP);

	if (!finish_op && !yankbuffer)
		opnum = 0;

	if (p_sc && (vpeekc() == NUL || KeyTyped == TRUE))
		premsg(NUL, NUL);
	State = NORMAL_BUSY;
	c = vgetc();

getcount:
	/* Pick up any leading digits and compute 'Prenum' */
	while ((c >= '1' && c <= '9') || (Prenum != 0 && (c == DEL || c == '0')))
	{
		if (c == DEL)
				Prenum /= 10;
		else
				Prenum = Prenum * 10 + (c - '0');
		if (Prenum < 0)			/* got too large! */
			Prenum = 999999999;
		premsg(ctrl_w ? Ctrl('W') : ' ', NUL);
		c = vgetc();
	}

/*
 * If we got CTRL-W there may be a/another count
 */
	if (c == Ctrl('W') && !ctrl_w)
	{
		ctrl_w = TRUE;
		opnum = Prenum;						/* remember first count */
		Prenum = 0;
		State = ONLYKEY;					/* no mapping for nchar, but keys */
		premsg(c, NUL);
		c = vgetc();						/* get next character */
		goto getcount;						/* jump back */
	}

	/*
	 * If we're in the middle of an operator (including after entering a yank
	 * buffer with ") AND we had a count before the
	 * operator, then that count overrides the current value of Prenum. What
	 * this means effectively, is that commands like "3dw" get turned into
	 * "d3w" which makes things fall into place pretty neatly.
	 * If you give a count before AND after the operator, they are multiplied.
	 */
	if (opnum != 0)
	{
			if (Prenum)
				Prenum *= opnum;
			else
				Prenum = opnum;
			opnum = 0;
	}

	Prenum1 = (Prenum == 0 ? 1 : Prenum);		/* Prenum often defaults to 1 */
	premsg(c, NUL);

	/*
	 * get an additional character if we need one
	 * for CTRL-W we already got it when looking for a count
	 */
	if (ctrl_w)
	{
		nchar = c;
		c = Ctrl('W');
		premsg(c, nchar);
	}
	else if (strchr("@zZtTfF[]mg'`\"", c) || (c == 'q' && !Recording && !Exec_reg) ||
										(c == 'r' && !VIsual.lnum))
	{
		State = NOMAPPING;
		nchar = vgetc();		/* no macro mapping for this char */
		premsg(c, nchar);
	}
	if (p_sc)
		flushbuf();		/* flush the premsg() characters onto the screen so we can
							see them while the command is being executed */

/*
 * For commands that don't get another character we can put the State back to
 * NORMAL and check for a window size change.
 */
	if (STRCHR("z:/?", c) == NULL)
		State = NORMAL;
	if (nchar == ESC)
	{
		CLEAROP;
		goto normal_end;
	}
	switch (c)
	{

/*
 * 0: Macros
 */
	  case 'q': 		/* (stop) recording into a named register */
		CHECKCLEAROP;
						/* command is ignored while executing a register */
		if (!Exec_reg && dorecord(nchar) == FAIL)
			CLEAROPBEEP;
		break;

	 case '@':			/* execute a named buffer */
		CHECKCLEAROP;
		while (Prenum1--)
		{
			if (doexecbuf(nchar) == FAIL)
			{
				CLEAROPBEEP;
				break;
			}
		}
		break;

/*
 * 1: Screen positioning commands
 */
	  case Ctrl('D'):
		flag = TRUE;

	  case Ctrl('U'):
		CHECKCLEAROP;
		if (Prenum)
			curwin->w_p_scroll = (Prenum > curwin->w_height) ? curwin->w_height : Prenum;
		n = (curwin->w_p_scroll <= curwin->w_height) ? curwin->w_p_scroll : curwin->w_height;
		if (flag)
		{
				curwin->w_topline += n;
				if (curwin->w_topline > curbuf->b_ml.ml_line_count)
					curwin->w_topline = curbuf->b_ml.ml_line_count;
				comp_Botline(curwin);		/* compute curwin->w_botline */
				(void)onedown(n);
		}
		else
		{
				if (n >= curwin->w_cursor.lnum)
					n = curwin->w_cursor.lnum - 1;
				Prenum1 = curwin->w_cursor.lnum - n;
				scrolldown(n);
				if (Prenum1 < curwin->w_cursor.lnum)
					curwin->w_cursor.lnum = Prenum1;
		}
		beginline(TRUE);
		updateScreen(VALID);
		break;

	  case Ctrl('B'):
	  case K_SUARROW:
		dir = BACKWARD;

	  case Ctrl('F'):
	  case K_SDARROW:
		CHECKCLEAROP;
		(void)onepage(dir, Prenum1);
		break;

	  case Ctrl('E'):
		CHECKCLEAROP;
		scrollup(Prenum1);
				/* We may have moved to another line -- webb */
		coladvance(curwin->w_curswant);
		updateScreen(VALID);
		break;

	  case Ctrl('Y'):
		CHECKCLEAROP;
		scrolldown(Prenum1);
				/* We may have moved to another line -- webb */
		coladvance(curwin->w_curswant);
		updateScreen(VALID);
		break;

	  case 'z':
		CHECKCLEAROP;
		if (isdigit(nchar))
		{
			/*
			 * we misuse some variables to be able to call premsg()
			 */
			operator = c;
			opnum = Prenum;
			Prenum = nchar - '0';
			for (;;)
			{
				premsg(' ', NUL);
				nchar = vgetc();
				State = NORMAL;
				if (nchar == DEL)
					Prenum /= 10;
				else if (isdigit(nchar))
					Prenum = Prenum * 10 + (nchar - '0');
				else if (nchar == CR)
				{
					win_setheight((int)Prenum);
					break;
				}
				else
				{
					CLEAROPBEEP;
					break;
				}
			}
			operator = NOP;
			break;
		}

		if (Prenum && Prenum != curwin->w_cursor.lnum)	/* line number given */
		{
			setpcmark();
			if (Prenum > curbuf->b_ml.ml_line_count)
				curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
			else
				curwin->w_cursor.lnum = Prenum;
		}
		State = NORMAL;			/* for updateScreen() */
		switch (nchar)
		{
		  case NL:				/* put curwin->w_cursor at top of screen */
		  case CR:
			beginline(TRUE);
		  case 't':
			curwin->w_topline = curwin->w_cursor.lnum;
			break;

		  case '.': 			/* put curwin->w_cursor in middle of screen */
		  case 'z':
			n = (curwin->w_height + plines(curwin->w_cursor.lnum)) / 2;
			goto dozcmd;

		  case '-': 			/* put curwin->w_cursor at bottom of screen */
		  case 'b':
			n = curwin->w_height;
			/* FALLTHROUGH */

	dozcmd:
			{
				register linenr_t	lp = curwin->w_cursor.lnum;
				register long		l = plines(lp);

				do
				{
					curwin->w_topline = lp;
					if (--lp == 0)
						break;
					l += plines(lp);
				} while (l <= n);
			}
			if (nchar != 'z' && nchar != 'b')
				beginline(TRUE);
			break;

		  case Ctrl('S'):	/* ignore CTRL-S and CTRL-Q to avoid problems */
		  case Ctrl('Q'):	/* with terminals that use xon/xoff */
		  	break;

		  default:
			CLEAROPBEEP;
		}
		updateScreen(VALID);
		break;

/*
 *	  2: Control commands
 */
	  case ':':
	    if (VIsual.lnum)
			goto dooperator;
		CHECKCLEAROP;
		/*
		 * translate "count:" into ":.,.+(count - 1)"
		 */
		if (Prenum)
		{
			stuffReadbuff((char_u *)".");
			if (Prenum > 1)
			{
				stuffReadbuff((char_u *)",.+");
				stuffnumReadbuff((long)Prenum - 1L);
			}
		}
		docmdline(NULL);
		modified = TRUE;
		break;

	  case K_HELP:
		CHECKCLEAROP;
		help();
		break;

	  case Ctrl('L'):
		CHECKCLEAROP;
		updateScreen(CLEAR);
		break;

	  case Ctrl('G'):
		CHECKCLEAROP;
		fileinfo(did_cd || Prenum);	/* print full name if count given or :cd used */
		break;

	  case K_CCIRCM:			/* CTRL-^, short for ":e #" */
		CHECKCLEAROPQ;
		(void)buflist_getfile((int)Prenum, (linenr_t)0, TRUE);
		break;

	  case 'Z': 		/* write, if changed, and exit */
		CHECKCLEAROPQ;
		if (nchar != 'Z')
		{
			CLEAROPBEEP;
			break;
		}
		stuffReadbuff((char_u *)":x\n");
		break;

	  case Ctrl(']'):			/* :ta to current identifier */
		CHECKCLEAROPQ;
	  case '*': 				/* / to current identifier or string */
	  case '#': 				/* ? to current identifier or string */
	  case 'K':					/* run program for current identifier */
		{
			register int 	col;
			register int	i;

			/*
			 * if i == 0: try to find an identifier
			 * if i == 1: try to find any string
			 */
			ptr = ml_get(curwin->w_cursor.lnum);
			for (i = 0;	i < 2; ++i)
			{
				/*
				 * skip to start of identifier/string
				 */
				col = curwin->w_cursor.col;
				while (ptr[col] != NUL &&
							(i == 0 ? !isidchar(ptr[col]) : iswhite(ptr[col])))
					++col;

				/*
				 * Back up to start of identifier/string. This doesn't match the
				 * real vi but I like it a little better and it shouldn't bother
				 * anyone.
				 */
				while (col > 0 && (i == 0 ? isidchar(ptr[col - 1]) :
							(!iswhite(ptr[col - 1]) && !isidchar(ptr[col - 1]))))
					--col;

				/*
				 * if identifier found or not '*' or '#' command, stop searching
				 */
				if (isidchar(ptr[col]) || (c != '*' && c != '#'))
					break;
			}
			/*
			 * did't find an identifier of string
			 */
			if (ptr[col] == NUL || (!isidchar(ptr[col]) && i == 0))
			{
				CLEAROPBEEP;
				break;
			}

			if (Prenum)
				stuffnumReadbuff(Prenum);
			switch (c)
			{
				case '*':
					stuffReadbuff((char_u *)"/");
					goto sow;

				case '#':
					stuffReadbuff((char_u *)"?");
sow:				if (i == 0)
						stuffReadbuff((char_u *)"\\<");
					break;

				case 'K':
					stuffReadbuff((char_u *)":! ");
					stuffReadbuff(p_kp);
					stuffReadbuff((char_u *)" ");
					break;
				default:
					stuffReadbuff((char_u *)":ta ");
			}

			/*
			 * Now grab the chars in the identifier
			 */
			while (i == 0 ? isidchar(ptr[col]) :
								(ptr[col] != NUL && !iswhite(ptr[col])))
			{
				stuffcharReadbuff(ptr[col]);
				++col;
			}
			if ((c == '*' || c == '#') && i == 0)
				stuffReadbuff((char_u *)"\\>");
			stuffReadbuff((char_u *)"\n");
		}
		break;

	  case Ctrl('T'):		/* backwards in tag stack */
			CHECKCLEAROPQ;
	  		dotag((char_u *)"", 2, (int)Prenum1);
			break;

/*
 * Cursor motions
 */
	  case 'G':
		mtype = MLINE;
		setpcmark();
		if (Prenum == 0 || Prenum > curbuf->b_ml.ml_line_count)
				curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
		else
				curwin->w_cursor.lnum = Prenum;
		beginline(TRUE);
		break;

	  case 'H':
	  case 'M':
		if (c == 'M')
				n = (curwin->w_height - curwin->w_empty_rows) / 2;
		else
				n = Prenum;
		mtype = MLINE;
		setpcmark();
		curwin->w_cursor.lnum = curwin->w_topline;
		while (n && onedown((long)1) == OK)
				--n;
		beginline(TRUE);
		break;

	  case 'L':
		mtype = MLINE;
		setpcmark();
		curwin->w_cursor.lnum = curwin->w_botline - 1;
		for (n = Prenum; n && oneup((long)1) == OK; n--)
				;
		beginline(TRUE);
		break;

	  case 'l':
	  case K_RARROW:
	  case ' ':
		mtype = MCHAR;
		mincl = FALSE;
		n = Prenum1;
		while (n--)
		{
			if (oneright() == FAIL)
			{
					/* space wraps to next line if 'whichwrap' bit 1 set */
					/* 'l' wraps to next line if 'whichwrap' bit 2 set */
					/* CURS_RIGHT wraps to next line if 'whichwrap' bit 3 set */
				if (((c == ' ' && (p_ww & 2)) ||
					 (c == 'l' && (p_ww & 4)) ||
					 (c == K_RARROW && (p_ww & 8))) &&
					 	curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
				{
					++curwin->w_cursor.lnum;
					curwin->w_cursor.col = 0;
					curwin->w_set_curswant = TRUE;
					continue;
				}
				if (operator == NOP)
					beep();
				else
				{
					if (lineempty(curwin->w_cursor.lnum))
						CLEAROPBEEP;
					else
					{
						mincl = TRUE;
						if (n)
							beep();
					}
				}
				break;
			}
		}
		break;

	  case Ctrl('H'):
	  case 'h':
	  case K_LARROW:
	  case DEL:
		mtype = MCHAR;
		mincl = FALSE;
		n = Prenum1;
		while (n--)
		{
			if (oneleft() == FAIL)
			{
					/* backspace and del wrap to previous line if 'whichwrap'
					 *											bit 0 set */
					/* 'h' wraps to previous line if 'whichwrap' bit 2 set */
					/* CURS_LEFT wraps to previous line if 'whichwrap' bit 3 set */
				if ((((c == Ctrl('H') || c == DEL) && (p_ww & 1)) ||
					 (c == 'h' && (p_ww & 4)) ||
					 (c == K_LARROW && (p_ww & 8))) &&
							curwin->w_cursor.lnum > 1)
				{
					--(curwin->w_cursor.lnum);
					coladvance(MAXCOL);
					curwin->w_set_curswant = TRUE;
					continue;
				}
				else if (operator != DELETE && operator != CHANGE)
					beep();
				else if (Prenum1 == 1)
					CLEAROPBEEP;
				break;
			}
		}
		break;

	  case '-':
		flag = TRUE;
		/* FALLTHROUGH */

	  case 'k':
	  case K_UARROW:
	  case Ctrl('P'):
		mtype = MLINE;
		if (oneup(Prenum1) == FAIL)
			CLEAROPBEEP;
		else if (flag)
			beginline(TRUE);
		break;

	  case '+':
	  case CR:
		flag = TRUE;
		/* FALLTHROUGH */

	  case 'j':
	  case K_DARROW:
	  case Ctrl('N'):
	  case NL:
		mtype = MLINE;
		if (onedown(Prenum1) == FAIL)
			CLEAROPBEEP;
		else if (flag)
			beginline(TRUE);
		break;

		/*
		 * This is a strange motion command that helps make operators more
		 * logical. It is actually implemented, but not documented in the
		 * real 'vi'. This motion command actually refers to "the current
		 * line". Commands like "dd" and "yy" are really an alternate form of
		 * "d_" and "y_". It does accept a count, so "d3_" works to delete 3
		 * lines.
		 */
	  case '_':
lineop:
		mtype = MLINE;
		if (onedown((long)(Prenum1 - 1)) == FAIL)
			CLEAROPBEEP;
		if (operator != YANK)			/* 'Y' does not move cursor */
			beginline(TRUE);
		break;

	  case '|':
		mtype = MCHAR;
		mincl = TRUE;
		beginline(FALSE);
		if (Prenum > 0)
			coladvance((colnr_t)(Prenum - 1));
		curwin->w_curswant = (colnr_t)(Prenum - 1);
			/* keep curswant at the column where we wanted to go, not where
				we ended; differs is line is too short */
		curwin->w_set_curswant = FALSE;
		break;

		/*
		 * Word Motions
		 */

	  case 'B':
		type = 1;
		/* FALLTHROUGH */

	  case 'b':
	  case K_SLARROW:
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;
		if (bck_word(Prenum1, type))
			CLEAROPBEEP;
		break;

	  case 'E':
		type = 1;
		/* FALLTHROUGH */

	  case 'e':
		mincl = TRUE;
		goto dowrdcmd;

	  case 'W':
		type = 1;
		/* FALLTHROUGH */

	  case 'w':
	  case K_SRARROW:
		mincl = FALSE;
		flag = TRUE;
		/*
		 * This is a little strange. To match what the real vi does, we
		 * effectively map 'cw' to 'ce', and 'cW' to 'cE', provided that we are
		 * not on a space or a TAB. This seems
		 * impolite at first, but it's really more what we mean when we say
		 * 'cw'.
		 * Another strangeness: When standing on the end of a word "ce" will
		 * change until the end of the next wordt, but "cw" will change only
		 * one character! This is done by setting type to 2.
		 */
		if (operator == CHANGE && (n = gchar_cursor()) != ' ' && n != TAB &&
																n != NUL)
		{
			mincl = TRUE;
			flag = FALSE;
			flag2 = TRUE;
		}

dowrdcmd:
		mtype = MCHAR;
		curwin->w_set_curswant = TRUE;
		if (flag)
			n = fwd_word(Prenum1, type, operator != NOP);
		else
			n = end_word(Prenum1, type, flag2);
		if (n)
		{
			CLEAROPBEEP;
			break;
		}
#if 0
		/*
		 * If we do a 'dw' for the last word in a line, we only delete the rest
		 * of the line, not joining the two lines, unless the current line is empty.
		 */
		if (operator == DELETE && Prenum1 == 1 &&
				curbuf->b_startop.lnum != curwin->w_cursor.lnum && !lineempty(startop.lnum))
		{
				curwin->w_cursor = curbuf->b_startop;
				while (oneright() == OK)
					;
				mincl = TRUE;
		}
#endif
		break;

	  case '$':
		mtype = MCHAR;
		mincl = TRUE;
		curwin->w_curswant = MAXCOL;				/* so we stay at the end */
		if (onedown((long)(Prenum1 - 1)) == FAIL)
		{
			CLEAROPBEEP;
			break;
		}
		break;

	  case '^':
		flag = TRUE;
		/* FALLTHROUGH */

	  case '0':
		mtype = MCHAR;
		mincl = FALSE;
		beginline(flag);
		break;

/*
 * 4: Searches
 */
	  case '?':
	  case '/':
		if (!getcmdline(c, searchbuff))
		{
			CLEAROP;
			break;
		}
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;

		n = dosearch(c, searchbuff, FALSE, Prenum1, TRUE, TRUE);
		if (n == 0)
			CLEAROP;
		else if (n == 2)
			mtype = MLINE;
		break;

	  case 'N':
		flag = 1;

	  case 'n':
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;
		if (!dosearch(0, NULL, flag, Prenum1, TRUE, TRUE))
			CLEAROP;
		break;

		/*
		 * Character searches
		 */
	  case 'T':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 't':
		type = 1;
		goto docsearch;

	  case 'F':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 'f':
docsearch:
		mtype = MCHAR;
		if (dir == BACKWARD)
			mincl = FALSE;
		else
			mincl = TRUE;
		curwin->w_set_curswant = TRUE;
		if (!searchc(nchar, dir, type, Prenum1))
			CLEAROPBEEP;
		break;

	  case ',':
		flag = 1;
		/* FALLTHROUGH */

	  case ';':
	    dir = flag;
	    goto docsearch;		/* nchar == NUL, thus repeat previous search */

		/*
		 * section or C function searches
		 */
	  case '[':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case ']':
		mtype = MCHAR;
		mincl = FALSE;

		/*
		 * "[f" or "]f" : Edit file under the cursor (same as "gf")
		 */
		if ((c == ']' || c == '[') && nchar == 'f')
			goto gotofile;

		/*
		 * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
		 */
		if ((c == '[' && (nchar == '{' || nchar == '(')) ||
		   ((c == ']' && (nchar == '}' || nchar == ')'))))
		{
			FPOS old_pos;

			old_pos = curwin->w_cursor;
			while (Prenum1--)
			{
				if ((pos = showmatch(nchar)) == NULL)
				{
					CLEAROPBEEP;
					break;
				}
				curwin->w_cursor = *pos;
			}
			curwin->w_cursor = old_pos;
			if (pos != NULL)
			{
				setpcmark();
				curwin->w_cursor = *pos;
				curwin->w_set_curswant = TRUE;
			}
			break;
		}

		/*
		 * "[[", "[]", "]]" and "][": move to start or end of function
		 */
		if (nchar == '[' || nchar == ']')
		{
			if (nchar == c)				/* "]]" or "[[" */
				flag = '{';
			else
				flag = '}';				/* "][" or "[]" */

			curwin->w_set_curswant = TRUE;
			/*
			 * Imitate strange vi behaviour: When using "]]" with an operator we
			 * also stop at '}'.
			 */
			if (!findpar(dir, Prenum1, flag,
							(operator != NOP && dir == FORWARD && flag == '{')))
				CLEAROPBEEP;
			break;
		}

		/*
		 * "[p" and "]p": put with indent adjustment
		 */
		if (nchar == 'p')
		{
			doput((c == ']') ? FORWARD : BACKWARD, Prenum1, TRUE);
			modified = TRUE;
			break;
		}

		/*
		 * end of '[' and ']': not a valid nchar
		 */
		CLEAROPBEEP;
		break;

	  case '%':
		mincl = TRUE;
	    if (Prenum)		/* {cnt}% : goto {cnt} percentage in file */
		{
			if (Prenum > 100)
				CLEAROPBEEP;
			else
			{
				mtype = MLINE;
				setpcmark();
						/* round up, so CTRL-G will give same value */
				curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count * Prenum + 99) / 100;
				beginline(TRUE);
			}
		}
		else			/* % : go to matching paren */
		{
			mtype = MCHAR;
			if ((pos = showmatch(NUL)) == NULL)
				CLEAROPBEEP;
			else
			{
				setpcmark();
				curwin->w_cursor = *pos;
				curwin->w_set_curswant = TRUE;
			}
		}
		break;

	  case '(':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case ')':
		mtype = MCHAR;
		if (c == ')')
			mincl = FALSE;
		else
			mincl = TRUE;
		curwin->w_set_curswant = TRUE;

		if (!findsent(dir, Prenum1))
			CLEAROPBEEP;
		break;

	  case '{':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case '}':
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;
		if (!findpar(dir, Prenum1, NUL, FALSE))
			CLEAROPBEEP;
		break;

/*
 * 5: Edits
 */
	  case '.':
		CHECKCLEAROPQ;
		if (start_redo(Prenum) == FAIL)
			CLEAROPBEEP;
		modified = TRUE;
		break;

	  case 'u':
	    if (VIsual.lnum)
			goto dooperator;
	  case K_UNDO:
		CHECKCLEAROPQ;
		u_undo((int)Prenum1);
		curwin->w_set_curswant = TRUE;
		modified = TRUE;
		break;

	  case Ctrl('R'):
		CHECKCLEAROPQ;
	  	u_redo((int)Prenum1);
		curwin->w_set_curswant = TRUE;
		modified = TRUE;
		break;

	  case 'U':
	    if (VIsual.lnum)
			goto dooperator;
		CHECKCLEAROPQ;
		u_undoline();
		curwin->w_set_curswant = TRUE;
		modified = TRUE;
		break;

	  case 'r':
	    if (VIsual.lnum)
		{
			c = 'c';
			goto dooperator;
		}
		CHECKCLEAROPQ;
		ptr = ml_get_cursor();
		if (STRLEN(ptr) < (unsigned)Prenum1)	/* not enough characters to replace */
		{
			CLEAROPBEEP;
			break;
		}
		/*
		 * Replacing with a line break or tab is done by edit(), because it
         * is complicated.
		 * Other characters are done below to avoid problems with things like
		 * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
		 */
		if (nchar == '\r' || nchar == '\n' || nchar == '\t')
		{
			prep_redo(Prenum1, 'r', nchar, NUL);
			stuffnumReadbuff(Prenum1);
			stuffcharReadbuff('R');
			stuffcharReadbuff(nchar);
			stuffcharReadbuff(ESC);
			break;
		}

		if (nchar == Ctrl('V'))				/* get another character */
		{
			c = Ctrl('V');
			nchar = get_literal(&type);
			if (type)						/* typeahead */
				stuffcharReadbuff(type);
		}
		else
			c = NUL;
		prep_redo(Prenum1, 'r', c, nchar);
		if (!u_save_cursor())				/* save line for undo */
			break;
			/*
			 * Get ptr again, because u_save will have released the line.
			 * At the same time we let know that the line will be changed.
			 */
		ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) + curwin->w_cursor.col;
		curwin->w_cursor.col += Prenum1 - 1;
		while (Prenum1--)					/* replace the characters */
			*ptr++ = nchar;
		curwin->w_set_curswant = TRUE;
		CHANGED;
		updateline();
		modified = TRUE;
		break;

	  case 'J':
	    if (VIsual.lnum)		/* join the visual lines */
		{
			if (curwin->w_cursor.lnum > VIsual.lnum)
			{
				Prenum = curwin->w_cursor.lnum - VIsual.lnum + 1;
				curwin->w_cursor.lnum = VIsual.lnum;
			}
			else
				Prenum = VIsual.lnum - curwin->w_cursor.lnum + 1;
			VIsual.lnum = 0;
		}
		CHECKCLEAROP;
		if (Prenum <= 1)
			Prenum = 2; 			/* default for join is two lines! */
		if (curwin->w_cursor.lnum + Prenum - 1 > curbuf->b_ml.ml_line_count)	/* beyond last line */
		{
			CLEAROPBEEP;
			break;
		}

		prep_redo(Prenum, 'J', NUL, NUL);
		dodojoin(Prenum, TRUE, TRUE);
		modified = TRUE;
		break;

	  case 'P':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 'p':
		CHECKCLEAROPQ;
		prep_redo(Prenum, c, NUL, NUL);
		doput(dir, Prenum1, FALSE);
		modified = TRUE;
		break;

	  case Ctrl('A'):			/* add to number */
	  case Ctrl('X'):			/* subtract from number */
		CHECKCLEAROPQ;
		if (doaddsub((int)c, Prenum1) == OK)
			prep_redo(Prenum1, c, NUL, NUL);
		modified = TRUE;
		break;

/*
 * 6: Inserts
 */
	  case 'A':
		curwin->w_set_curswant = TRUE;
		while (oneright() == OK)
				;
		/* FALLTHROUGH */

	  case 'a':
		CHECKCLEAROPQ;
		/* Works just like an 'i'nsert on the next character. */
		if (u_save_cursor())
		{
			if (!lineempty(curwin->w_cursor.lnum))
				inc_cursor();
			startinsert(c, FALSE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'I':
		beginline(TRUE);
		/* FALLTHROUGH */

	  case 'i':
		CHECKCLEAROPQ;
		if (u_save_cursor())
		{
			startinsert(c, FALSE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'o':
	  	if (VIsual.lnum)	/* switch start and end of visual */
		{
			Prenum = VIsual.lnum;
			VIsual.lnum = curwin->w_cursor.lnum;
			curwin->w_cursor.lnum = Prenum;
			if (VIsual.col != VISUALLINE)
			{
				n = VIsual.col;
				VIsual.col = curwin->w_cursor.col;
				curwin->w_cursor.col = (int)n;
				curwin->w_set_curswant = TRUE;
			}
			break;
		}
		CHECKCLEAROP;
		if (u_save(curwin->w_cursor.lnum, (linenr_t)(curwin->w_cursor.lnum + 1)) &&
							Opencmd(FORWARD, TRUE, TRUE))
		{
			startinsert('o', TRUE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'O':
		CHECKCLEAROPQ;
		if (u_save((linenr_t)(curwin->w_cursor.lnum - 1), curwin->w_cursor.lnum) && Opencmd(BACKWARD, TRUE, TRUE))
		{
			startinsert('O', TRUE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'R':
	    if (VIsual.lnum)
		{
			c = 'c';
			VIsual.col = VISUALLINE;
			goto dooperator;
		}
		CHECKCLEAROPQ;
		if (u_save_cursor())
		{
			startinsert('R', FALSE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

/*
 * 7: Operators
 */
	  case '~': 		/* swap case */
	  /*
	   * if tilde is not an operator and Visual is off: swap case
	   * of a single character
	   */
		if (!p_to && !VIsual.lnum)
		{
			CHECKCLEAROPQ;
			if (lineempty(curwin->w_cursor.lnum))
			{
				CLEAROPBEEP;
				break;
			}
			prep_redo(Prenum, '~', NUL, NUL);

			if (!u_save_cursor())
				break;

			for (; Prenum1 > 0; --Prenum1)
			{
				if (gchar_cursor() == NUL)
					break;
				swapchar(&curwin->w_cursor);
				inc_cursor();
			}

			curwin->w_set_curswant = TRUE;
			CHANGED;
			updateline();
			modified = TRUE;
			break;
		}
		/*FALLTHROUGH*/

	  case 'd':
	  case 'c':
	  case 'y':
	  case '>':
	  case '<':
	  case '!':
	  case '=':
	  case 'Q':
dooperator:
		n = STRCHR(opchars, c) - opchars + 1;
		if (n == operator)		/* double operator works on lines */
			goto lineop;
		CHECKCLEAROP;
		if (Prenum != 0)
			opnum = Prenum;
		curbuf->b_startop = curwin->w_cursor;
		operator = (int)n;
		break;

/*
 * 8: Abbreviations
 */

	 /* when Visual the next commands are operators */
	  case 'S':
	  case 'Y':
	  case 'D':
	  case 'C':
	  case 'x':
	  case 'X':
	  case 's':
	  	if (VIsual.lnum)
		{
			static char_u trans[] = "ScYyDdCcxdXdsc";

			if (isupper(c) && !Visual_block)		/* uppercase means linewise */
				VIsual.col = VISUALLINE;
			c = *(STRCHR(trans, c) + 1);
			goto dooperator;
		}

	  case '&':
		CHECKCLEAROPQ;
		if (Prenum)
			stuffnumReadbuff(Prenum);

		if (c == 'Y' && p_ye)
			c = 'Z';
		{
				static char_u *(ar[9]) = {(char_u *)"dl", (char_u *)"dh", (char_u *)"d$", (char_u *)"c$", (char_u *)"cl", (char_u *)"cc", (char_u *)"yy", (char_u *)"y$", (char_u *)":s\r"};
				static char_u *str = (char_u *)"xXDCsSYZ&";

				stuffReadbuff(ar[(int)(STRCHR(str, c) - str)]);
		}
		break;

/*
 * 9: Marks
 */

	  case 'm':
		CHECKCLEAROP;
		if (setmark(nchar) == FAIL)
			CLEAROPBEEP;
		break;

	  case '\'':
		flag = TRUE;
		/* FALLTHROUGH */

	  case '`':
		pos = getmark(nchar, (operator == NOP));
		if (pos == (FPOS *)-1)	/* jumped to other file */
		{
			if (flag)
				beginline(TRUE);
			break;
		}

		if (pos != NULL)
			setpcmark();

cursormark:
		if (pos == NULL || pos->lnum == 0)
			CLEAROPBEEP;
		else
		{
			curwin->w_cursor = *pos;
			if (flag)
				beginline(TRUE);
		}
		mtype = flag ? MLINE : MCHAR;
		mincl = FALSE;		/* ignored if not MCHAR */
		curwin->w_set_curswant = TRUE;
		break;

	case Ctrl('O'):			/* goto older pcmark */
		Prenum1 = -Prenum1;
		/* FALLTHROUGH */

	case Ctrl('I'):			/* goto newer pcmark */
		CHECKCLEAROPQ;
		pos = movemark((int)Prenum1);
		if (pos == (FPOS *)-1)	/* jump to other file */
		{
			curwin->w_set_curswant = TRUE;
			break;
		}
		goto cursormark;

/*
 * 10. Buffer setting
 */
	  case '"':
		CHECKCLEAROP;
		if (nchar != NUL && is_yank_buffer(nchar, FALSE))
		{
			yankbuffer = nchar;
			opnum = Prenum;		/* remember count before '"' */
		}
		else
			CLEAROPBEEP;
		break;

/*
 * 11. Visual
 */
 	  case 'v':
	  case 'V':
	  case Ctrl('V'):
		CHECKCLEAROP;
		Visual_block = FALSE;

			/* stop Visual */
		if (VIsual.lnum)
		{
			VIsual.lnum = 0;
			updateScreen(NOT_VALID);		/* delete the inversion */
		}
			/* start Visual */
		else
		{
			if (!didwarn && set_highlight('v') == FAIL)/* cannot highlight */
			{
				EMSG("Warning: terminal cannot highlight");
				didwarn = TRUE;
			}
			if (Prenum)						/* use previously selected part */
			{
				if (!resel_Visual_type)		/* there is none */
				{
					beep();
					break;
				}
				VIsual = curwin->w_cursor;
				if (resel_Visual_nlines > 1)
					curwin->w_cursor.lnum += resel_Visual_nlines * Prenum - 1;
				switch (resel_Visual_type)
				{
				case 'V':	VIsual.col = VISUALLINE;
							break;

				case Ctrl('V'):
							Visual_block = TRUE;
							break;

				case 'v':		
							if (resel_Visual_nlines <= 1)
								curwin->w_cursor.col += resel_Visual_col * Prenum - 1;
							else
								curwin->w_cursor.col = resel_Visual_col;
							break;
				}
				if (resel_Visual_col == MAXCOL)
				{
					curwin->w_curswant = MAXCOL;
					coladvance(MAXCOL);
				}
				else if (Visual_block)
					coladvance((colnr_t)(curwin->w_virtcol + resel_Visual_col * Prenum - 1));
				curs_columns(TRUE);			/* recompute w_virtcol */
				updateScreen(NOT_VALID);	/* show the inversion */
			}
			else
			{
				VIsual = curwin->w_cursor;
				if (c == 'V')				/* linewise */
					VIsual.col = VISUALLINE;
				else if (c == Ctrl('V'))	/* blockwise */
					Visual_block = TRUE;
				updateline();				/* start the inversion */
			}
		}
		break;

/*
 * 12. Suspend
 */

 	case Ctrl('Z'):
		CLEAROP;
		VIsual.lnum = 0;					/* stop Visual */
		stuffReadbuff((char_u *)":st\r");	/* with autowrite */
		break;

/*
 * 13. Window commands
 */

 	case Ctrl('W'):
		CHECKCLEAROP;
		do_window(nchar, Prenum);			/* everything is in window.c */
		break;

/*
 *   14. extended commands (starting with 'g')
 */
 	case 'g':
		switch (nchar)
		{
						/*
						 * "gf": goto file, edit file under cursor
						 * "]f" and "[f": can also be used.
						 */
			case 'f':
gotofile:
						ptr = file_name_at_cursor();
							/* do autowrite if necessary */
						if (curbuf->b_changed && curbuf->b_nwindows <= 1 && !p_hid)
							autowrite(curbuf);
						if (ptr != NULL)
						{
							setpcmark();
							stuffReadbuff((char_u *) ":e ");
							stuffReadbuff(ptr);
							stuffReadbuff((char_u *) "\n");
							free(ptr);
						}
						else
							CLEAROPBEEP;
						break;

						/*
						 * "gs": goto sleep
						 */
			case 's':	while (Prenum1-- && !got_int)
						{
							sleep(1);
							breakcheck();
						}
						break;

			default:	CLEAROPBEEP;
						break;
		}
		break;

/*
 * The end
 */
	  case ESC:
	    if (VIsual.lnum)
		{
			VIsual.lnum = 0;			/* stop Visual */
			updateScreen(NOT_VALID);
			CLEAROP;					/* don't beep */
			break;
		}
		/* Don't drop through and beep if we are canceling a command: */
		else if (operator != NOP || opnum || Prenum || yankbuffer)
		{
			CLEAROP;					/* don't beep */
			break;
		}
		/* FALLTHROUGH */

	  default:					/* not a known command */
		CLEAROPBEEP;
		break;

	}	/* end of switch on command character */

/*
 * if we didn't start or finish an operator, reset yankbuffer, unless we
 * need it later.
 */
	if (!finish_op && !operator && strchr("\"DCYSsXx.", c) == NULL)
		yankbuffer = 0;

	/*
	 * If an operation is pending, handle it...
	 */
	if ((VIsual.lnum || finish_op) && operator != NOP)
	{
		if (operator != YANK && !VIsual.lnum)		/* can't redo yank */
		{
			prep_redo(Prenum, opchars[operator - 1], c, nchar);
			if (c == '/' || c == '?')				/* was a search */
			{
				AppendToRedobuff(searchbuff);
				AppendToRedobuff(NL_STR);
			}
		}

		if (redo_Visual_busy)
		{
			curbuf->b_startop = curwin->w_cursor;
			curwin->w_cursor.lnum += redo_Visual_nlines - 1;
			switch (redo_Visual_type)
			{
			case 'V':	VIsual.col = VISUALLINE;
						break;

			case Ctrl('V'):
						Visual_block = TRUE;
						break;

			case 'v':		
						if (redo_Visual_nlines <= 1)
							curwin->w_cursor.col += redo_Visual_col - 1;
						else
							curwin->w_cursor.col = redo_Visual_col;
						break;
			}
			if (redo_Visual_col == MAXCOL)
			{
				curwin->w_curswant = MAXCOL;
				coladvance(MAXCOL);
			}
			Prenum = redo_Visual_Prenum;
			if (Prenum == 0)
				Prenum1 = 1L;
			else
				Prenum1 = Prenum;
		}
		else if (VIsual.lnum)
			curbuf->b_startop = VIsual;

		if (lt(curbuf->b_startop, curwin->w_cursor))
		{
			curbuf->b_endop = curwin->w_cursor;
			curwin->w_cursor = curbuf->b_startop;
		}
		else
		{
			curbuf->b_endop = curbuf->b_startop;
			curbuf->b_startop = curwin->w_cursor;
		}
		nlines = curbuf->b_endop.lnum - curbuf->b_startop.lnum + 1;

		if (VIsual.lnum || redo_Visual_busy)
		{
			if (Visual_block)				/* block mode */
			{
				startvcol = getvcol(curwin, &(curbuf->b_startop), 2);
				n = getvcol(curwin, &(curbuf->b_endop), 2);
				if (n < startvcol)
					startvcol = (colnr_t)n;

			/* if '$' was used, get endvcol from longest line */
				if (curwin->w_curswant == MAXCOL)
				{
					curwin->w_cursor.col = MAXCOL;
					endvcol = 0;
					for (curwin->w_cursor.lnum = curbuf->b_startop.lnum; curwin->w_cursor.lnum <= curbuf->b_endop.lnum; ++curwin->w_cursor.lnum)
						if ((n = getvcol(curwin, &curwin->w_cursor, 3)) > endvcol)
							endvcol = (colnr_t)n;
					curwin->w_cursor = curbuf->b_startop;
				}
				else if (redo_Visual_busy)
					endvcol = startvcol + redo_Visual_col - 1;
				else
				{
					endvcol = getvcol(curwin, &(curbuf->b_startop), 3);
					n = getvcol(curwin, &(curbuf->b_endop), 3);
					if (n > endvcol)
						endvcol = (colnr_t)n;
				}
				coladvance(startvcol);
			}

	/*
	 * prepare to reselect and redo Visual: this is based on the size
	 * of the Visual text
	 */
			if (Visual_block)
				resel_Visual_type = Ctrl('V');
			else if (VIsual.col == VISUALLINE)
				resel_Visual_type = 'V';
			else
				resel_Visual_type = 'v';
			if (curwin->w_curswant == MAXCOL)
				resel_Visual_col = MAXCOL;
			else if (Visual_block)
				resel_Visual_col = endvcol - startvcol + 1;
			else if (nlines > 1)
				resel_Visual_col = curbuf->b_endop.col;
			else
				resel_Visual_col = curbuf->b_endop.col - curbuf->b_startop.col + 1;
			resel_Visual_nlines = nlines;
			if (operator != YANK && operator != COLON)	/* can't redo yank and : */
			{
				prep_redo(0L, 'v', opchars[operator - 1], NUL);
				redo_Visual_type = resel_Visual_type;
				redo_Visual_col = resel_Visual_col;
				redo_Visual_nlines = resel_Visual_nlines;
				redo_Visual_Prenum = Prenum;
			}

			/*
			 * Mincl defaults to TRUE.
			 * If endop is on a NUL (empty line) mincl becomes FALSE
			 * This makes "d}P" and "v}dP" work the same.
			 */
			mincl = TRUE;
			if (VIsual.col == VISUALLINE)
				mtype = MLINE;
			else
			{
				mtype = MCHAR;
				if (*ml_get_pos(&(curbuf->b_endop)) == NUL)
					mincl = FALSE;
			}

			redo_Visual_busy = FALSE;
			/*
			 * Switch Visual off now, so screen updating does
			 * not show inverted text when the screen is redrawn.
			 * With YANK and sometimes with COLON and FILTER there is no screen
			 * redraw, so it is done here to remove the inverted part.
			 */
			VIsual.lnum = 0;
			if (operator == YANK || operator == COLON || operator == FILTER)
				updateScreen(NOT_VALID);
		}
		else if (operator == LSHIFT || operator == RSHIFT)
			Prenum1 = 1L;		/* if not visual mode: shift one indent */

		curwin->w_set_curswant = 1;

			/* no_op is set when start and end are the same */
		no_op = (mtype == MCHAR && !mincl && equal(curbuf->b_startop, curbuf->b_endop));

	/*
	 * If the end of an operator is in column one while mtype is MCHAR and mincl
	 * is FALSE, we put endop after the last character in the previous line.
	 * If startop is on or before the first non-blank in the line, the operator
	 * becomes linewise (strange, but that's the way vi does it).
	 */
		if (mtype == MCHAR && mincl == FALSE && curbuf->b_endop.col == 0 && nlines > 1)
		{
			--nlines;
			--curbuf->b_endop.lnum;
			if (inindent())
				mtype = MLINE;
			else
			{
				curbuf->b_endop.col = STRLEN(ml_get(curbuf->b_endop.lnum));
				if (curbuf->b_endop.col)
				{
					--curbuf->b_endop.col;
					mincl = TRUE;
				}
			}
		}
		switch (operator)
		{
		  case LSHIFT:
		  case RSHIFT:
			doshift(operator, TRUE, (int)Prenum1);
			modified = TRUE;
			break;

		  case DELETE:
			if (!no_op)
			{
				dodelete();
				modified = TRUE;
			}
			break;

		  case YANK:
			if (!no_op)
				(void)doyank(FALSE);
			break;

		  case CHANGE:
			dochange();
			modified = TRUE;
			command_busy = TRUE;
			break;

		  case FILTER:
			bangredo = TRUE;			/* dobang() will put cmd in redo buffer */

		  case INDENT:
		  case COLON:
dofilter:
			sprintf((char *)IObuff, ":%ld,%ld", (long)curbuf->b_startop.lnum, (long)curbuf->b_endop.lnum);
			stuffReadbuff(IObuff);
			if (operator != COLON)
				stuffReadbuff((char_u *)"!");
			if (operator == INDENT)
			{
				stuffReadbuff(p_ep);
				stuffReadbuff((char_u *)"\n");
			}
			else if (operator == FORMAT)
			{
				stuffReadbuff(p_fp);
				stuffReadbuff((char_u *)"\n");
			}
				/*	docmdline() does the rest */
			break;

		  case TILDE:
		  case UPPER:
		  case LOWER:
			if (!no_op)
			{
				dotilde();
				modified = TRUE;
			}
			break;

		  case FORMAT:
			if (*p_fp != NUL)
				goto dofilter;		/* use external command */
			doformat();				/* use internal function */
			modified = TRUE;
			break;

		  default:
			CLEAROPBEEP;
		}
		operator = NOP;
		Visual_block = FALSE;
		yankbuffer = 0;
	}

normal_end:
	premsg(-1, NUL);

	if (restart_edit && operator == NOP && VIsual.lnum == 0 && !command_busy && stuff_empty() && yankbuffer == 0)
	{
		startinsert(restart_edit, FALSE, 1L);
		modified = TRUE;
	}

	checkpcmark();			/* check if we moved since setting pcmark */

/*
 * TEMPORARY: update the other windows for the current buffer if modified
 */
	if (modified)
	{
		WIN		*wp;

        for (wp = firstwin; wp; wp = wp->w_next)
			if (wp != curwin && wp->w_buffer == curbuf)
			{
				cursor_off();
				wp->w_redr_type = NOT_VALID;
				win_update(wp);
			}
	}
}
void handle_key_press(char key) {
	char *tri_code;

	// Standard key presses...

	// Default "How Many Cans?" screen
	if (lcd_state == LCD_STATE_DEFAULT) {
		// 1 - 9
		if (key >= 49 && key <= 57) {
			write_char(key);
			cursor_left(1);
		}
	}

	// Admin menu
	if (lcd_state == LCD_STATE_ADMIN) {
		if (key == '#') {
			write_admin_menu(1);
		}
		else if (key == '*') {
			write_admin_menu(-1);
		}
		// 0 - 9
		if (key >= 48 && key <= 57) {
			switch (key) {
				// Exit
				case '0':
					lcd_reset();
					break;
				// Restock
				case '1':
					// Unlock teh door
					break;
				// Enroll
				case '2':
					// Enroll
					break;
				// Drug deal
				case '3':
					// Deduct from user 'drugs'
					// Open door
					break;
			};
		}
	}

	// Tri codes...

	// *69 for admin
	if (tri_code = (char *)get_tri_code()) {
		if (strcmp(tri_code, "*69") == 0) {
			clear_screen();
			cursor_blink_off();
			cursor_off();
			write_string("Admin mode...\n* & # to scroll");

			admin_line = 0;

			sleep(2);

			write_admin_menu(0);

			lcd_state = LCD_STATE_ADMIN;
		}
	}
}
Example #17
0
void edit_game(FILE *fp) {
    int quit = 0, m = 0;
    int x, y, z, a, c, xp, yp;

    while(!quit && m >= 0) {
        xp = maze[m].xp, yp = maze[m].yp;

        clear_screen();
        cursor(0, 0);

        for(y = 0; y < 22; y ++) {
            cursor(0, y);
                
            for(x = 0; x < 80; x ++) {
                if(x == xp && y == yp) printf("\017");
                else if(x == maze[m].xp && y == maze[m].yp) printf("\001");
                else {
                    switch(maze[m].sq[x][y].type) {
                    case MAZE_BLANK: printf(" "); break;
                    case MAZE_KEY: printf("\013"); break;
                    /*case MAZE_NOKEY: printf("\372"); break;*/
                    case MAZE_DOOR: printf("\376"); break;
                    case MAZE_FINISH: printf("\257"); break;
                    default: printf("\333"); break;
                    }
                }
            }
        }

        cursor_off();

        while(!quit) {
            cursor(0, 0);
    
            if(xp > 0) maze[m].sq[xp-1][yp].ex = 1;
            if(yp > 0) maze[m].sq[xp][yp-1].ex = 1;
            if(xp < 79) maze[m].sq[xp+1][yp].ex = 1;
            if(yp < 21) maze[m].sq[xp][yp+1].ex = 1;
            if(xp > 0 && yp > 0) maze[m].sq[xp-1][yp-1].ex = 1;
            if(xp > 0 && yp < 21) maze[m].sq[xp-1][yp+1].ex = 1;
            if(xp < 79 && yp > 0) maze[m].sq[xp+1][yp-1].ex = 1;
            if(xp < 79 && yp < 21) maze[m].sq[xp+1][yp+1].ex = 1;
    
            z = xp-1;
            if(z < 0) z = 0;
    
            for(y = yp-1 < 0 ? 0 : yp-1; y < yp+2 && y < 22; y ++) {
                cursor(z, y);
                
                for(x = z; x < xp+2 && x < 80; x ++) {
                    if(x == xp && y == yp) printf("\017");
                    else if(x == maze[m].xp && y == maze[m].yp) printf("\001");
                    else {
                        switch(maze[m].sq[x][y].type) {
                        case MAZE_BLANK: printf(" "); break;
                        case MAZE_KEY: printf("\013"); break;
                        /*case MAZE_NOKEY: printf("\372"); break;*/
                        case MAZE_DOOR: printf("\376"); break;
                        case MAZE_FINISH: printf("\257"); break;
                        default: printf("\333"); break;
                        }
                    }
                }
            }

            cursor(0, 22);
            printf("MAZE %c    ", m+'A');

            switch(maze[m].sq[xp][yp].type) {
            case MAZE_KEY:
                printf("Key %c ", maze[m].sq[xp][yp].data < 26 ?
                    maze[m].sq[xp][yp].data + 'A'
                    : maze[m].sq[xp][yp].data + 'a' - 26);
                break;
            case MAZE_DOOR:
                printf("Door %c", maze[m].sq[xp][yp].data < 26 ?
                    maze[m].sq[xp][yp].data + 'A'
                    : maze[m].sq[xp][yp].data + 'a' - 26);
                break;
            case MAZE_FINISH:
                printf("Fin %c ", maze[m].sq[xp][yp].data < 0 ?
                    '>' : maze[m].sq[xp][yp].data + 'A');
                break;
            default: printf("      "); break;
            }
    
            switch((c=getch())) {
            case 0:  /* extended */
                switch((c=getch())) {
                case 72:  /* up */
                    if(yp > 0) yp --;
                    break;
                case 80:  /* down */
                    if(yp < 21) yp ++;
                    break;
                case 75:  /* left */
                    if(xp > 0) xp --;
                    break;
                case 77:  /* right */
                    if(xp < 79) xp ++;
                    break;
                case 15:  /* shift-tab */
                    if(m > 0) {
                        m --;
                        quit = 1;
                    }
                    break;
                }
                break;
            case 27: quit = 2; break;  /* esc */
            case ' ': maze[m].sq[xp][yp].type = MAZE_BLANK; break;
            case '.': maze[m].sq[xp][yp].type = MAZE_WALL; break;
            case '+':
                maze[m].sq[xp][yp].type = MAZE_KEY;
                while(!isalpha(c = getch())) ;
                maze[m].sq[xp][yp].data = (isupper(c) ? c-'A' : c-'a'+26);
                break;
            case '-':
                maze[m].sq[xp][yp].type = MAZE_DOOR;
                while(!isalpha(c = getch())) ;
                maze[m].sq[xp][yp].data = (isupper(c) ? c-'A' : c-'a'+26);
                break;
            case '>':
                maze[m].sq[xp][yp].type = MAZE_FINISH;
                c = getch();
                maze[m].sq[xp][yp].data = (c>='A' && c<='M' ? c-'A' : -1);
                break;
            case 's':
                cursor(maze[m].xp, maze[m].yp);
                printf(" ");
                maze[m].xp = xp, maze[m].yp = yp;
                maze[m].sq[xp][yp].type = MAZE_BLANK;
                break;
            case 'l':
                for(x = 0; x < 80; x ++) {
                    for(y = 0; y < 22; y ++) {
                        if(maze[m].sq[x][y].type == MAZE_DOOR ||
                            maze[m].sq[x][y].type == MAZE_KEY) {

                            cursor(x, y);
                            printf("%c", maze[m].sq[x][y].data < 26 ?
                                maze[m].sq[x][y].data + 'A' :
                                maze[m].sq[x][y].data + 'a'-26);
                        }
                    }
                }

                getch();

                for(x = 0; x < 80; x ++) {
                    for(y = 0; y < 22; y ++) {
                        if(maze[m].sq[x][y].type == MAZE_DOOR) {
                            cursor(x, y);
                            printf("\376");
                        }
                        else if(maze[m].sq[x][y].type == MAZE_KEY) {
                            cursor(x, y);
                            printf("\013");
                        }
                    }
                }
                
                break;
            case '\t':
                if(m < 13) {
                    m ++;
                    quit = 1;
                }
                break;
            }

            /*cursor(0, 24);
            printf("%3i", c);*/
        }
        
        quit --;
    }

    fputs("TMAZE\n", fp);
    for(z = 0; z < 13; z ++) {
        for(x = 0; x < 80; x ++) {
            for(y = 0; y < 22; y ++) {
                if(maze[z].sq[x][y].type != MAZE_BLANK) x = 81;
            }
        }

        if(x > 80) {
            putc(z+'A', fp);
            putc('\n', fp);
            
            for(y = 0; y < 22; y ++) {
                for(a = 79; a >= 0; a --) {
                    if(maze[z].sq[a][y].type != MAZE_BLANK ||
                        (maze[z].xp == a && maze[z].yp == y)) break;
                }

                for(x = 0; x <= a; x ++) {
                    if(x == maze[z].xp && y == maze[z].yp) putc(':', fp);
                    else switch(maze[z].sq[x][y].type) {
                    case MAZE_BLANK: putc(' ', fp); break;
                    case MAZE_WALL: putc('.', fp); break;
                    case MAZE_KEY: case MAZE_NOKEY:
                        putc('+', fp);
                        putc(maze[z].sq[x][y].data < 26 ?
                            maze[z].sq[x][y].data + 'A' :
                            maze[z].sq[x][y].data + 'a'-26, fp);
                        break;
                    case MAZE_DOOR:
                        putc('-', fp);
                        putc(maze[z].sq[x][y].data < 26 ? maze[z].sq[x][y].data + 'A' :
                            maze[z].sq[x][y].data + 'a'-26, fp);
                        break;
                    case MAZE_FINISH:
                        putc('>', fp);
                        if(maze[z].sq[x][y].data == -1) putc('>', fp);
                        else putc(maze[z].sq[x][y].data + 'A', fp);
                        break;
                    }
                }

                putc('\n', fp);
            }
        }
    }

    cursor_on();
}
Example #18
0
void play_game(void) {
    int quit = 0, key[52], m = 0;
    int x, y, z, c, xp, yp;

    while(!quit && m >= 0) {
        xp = maze[m].xp, yp = maze[m].yp;

        for(x = 0; x < 52; x ++) key[x] = 0;
        
        for(x = 0; x < 80; x ++) {
            for(y = 0; y < 22; y ++) {
                maze[m].sq[x][y].ex = 0;
            }
        }

        clear_screen();
        cursor(0, 0);

        for(x = 0; x < 80; x ++) {
            printf("\260\260\260\260\260\260\260\260\260\260"
                "\260\260\260\260\260\260\260\260\260\260\260\260");
        }

        cursor_off();

        while(!quit) {
            cursor(0, 0);
    
            if(xp > 0) maze[m].sq[xp-1][yp].ex = 1;
            if(yp > 0) maze[m].sq[xp][yp-1].ex = 1;
            if(xp < 79) maze[m].sq[xp+1][yp].ex = 1;
            if(yp < 21) maze[m].sq[xp][yp+1].ex = 1;
            
            if(xp > 0 && yp > 0) maze[m].sq[xp-1][yp-1].ex = 1;
            if(xp > 0 && yp < 21) maze[m].sq[xp-1][yp+1].ex = 1;
            if(xp < 79 && yp > 0) maze[m].sq[xp+1][yp-1].ex = 1;
            if(xp < 79 && yp < 21) maze[m].sq[xp+1][yp+1].ex = 1;
    
            z = xp-1;
            if(z < 0) z = 0;
    
            for(y = yp-1 < 0 ? 0 : yp-1; y < yp+2 && y < 22; y ++) {
                cursor(z, y);
                
                for(x = z; x < xp+2 && x < 80; x ++) {
                    if(x == xp && y == yp) printf("\017");
                    else if(maze[m].sq[x][y].ex) {
                        switch(maze[m].sq[x][y].type) {
                        case MAZE_BLANK: printf(" "); break;
                        case MAZE_KEY: printf("\013"); break;
                        case MAZE_NOKEY: printf("\372"); break;
                        case MAZE_DOOR: printf("\376"); break;
                        case MAZE_FINISH: printf("\257"); break;
                        default: printf("\333"); break;
                        }
                    }
                }
            }
    
            switch((c=getch())) {
            case 0:  /* extended */
                switch((c=getch())) {
                case 72:  /* up */
                    if(yp > 0) {
                        switch(maze[m].sq[xp][yp-1].type) {
                        case MAZE_FINISH:
                            m = maze[m].sq[xp][yp-1].data;
                            quit = 1;
                            break;
                        case MAZE_NOKEY:
                        case MAZE_BLANK: yp --; break;
                        case MAZE_WALL: break;
                        case MAZE_KEY:
                            yp --;
                            key[maze[m].sq[xp][yp].data] = 1;
                            maze[m].sq[xp][yp].type = MAZE_NOKEY;
                            break;
                        case MAZE_DOOR:
                            if(key[maze[m].sq[xp][yp-1].data]) yp --;
                            break;
                        }
                    }
                    break;
                case 80:  /* down */
                    if(yp < 21) {
                        switch(maze[m].sq[xp][yp+1].type) {
                        case MAZE_FINISH:
                            m = maze[m].sq[xp][yp+1].data;
                            quit = 1;
                            break;
                        case MAZE_NOKEY:
                        case MAZE_BLANK: yp ++; break;
                        case MAZE_WALL: break;
                        case MAZE_KEY:
                            yp ++;
                            key[maze[m].sq[xp][yp].data] = 1;
                            maze[m].sq[xp][yp].type = MAZE_NOKEY;
                            break;
                        case MAZE_DOOR:
                            if(key[maze[m].sq[xp][yp+1].data]) yp ++;
                            break;
                        }
                    }
                    break;
                case 75:  /* left */
                    if(xp > 0) {
                        switch(maze[m].sq[xp-1][yp].type) {
                        case MAZE_FINISH:
                            m = maze[m].sq[xp-1][yp].data;
                            quit = 1;
                            break;
                        case MAZE_NOKEY:
                        case MAZE_BLANK: xp --; break;
                        case MAZE_WALL: break;
                        case MAZE_KEY:
                            xp --;
                            key[maze[m].sq[xp][yp].data] = 1;
                            maze[m].sq[xp][yp].type = MAZE_NOKEY;
                            break;
                        case MAZE_DOOR:
                            if(key[maze[m].sq[xp-1][yp].data]) xp --;
                            break;
                        }
                    }
                    break;
                case 77:  /* right */
                    if(xp < 79) {
                        switch(maze[m].sq[xp+1][yp].type) {
                        case MAZE_FINISH:
                            m = maze[m].sq[xp+1][yp].data;
                            quit = 1;
                            break;
                        case MAZE_NOKEY:
                        case MAZE_BLANK: xp ++; break;
                        case MAZE_WALL: break;
                        case MAZE_KEY:
                            xp ++;
                            key[maze[m].sq[xp][yp].data] = 1;
                            maze[m].sq[xp][yp].type = MAZE_NOKEY;
                            break;
                        case MAZE_DOOR:
                            if(key[maze[m].sq[xp+1][yp].data]) xp ++;
                            break;
                        }
                    }
                    break;
                }
                break;
            case 27: quit = 2; break;  /* esc */
            }
    
            /*cursor(0, 24);
            printf("%3i", c);*/
        }
        
        quit --;
    }

    cursor_on();
}