/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 16-Nov-85 | [1.56] Created * 23-Nov-85 | [1.91] Wait for mouse cursor up; hide mouse cursor during bit * | flip * 11-Dec-85 | [1.164] ^L refreshes screen * 11-Dec-85 | [1.167] Hide mouse cursor before displaying keyboard char * 29-Dec-85 | [1.270] Do not allow Enter key to work unless in Alter mode * 11-Jan-86 | [1.290] Handle user hitting function keys...support mouseless * | system * 11-Jan-86 | [1.293] Do not update character or store it if console display * | not active * 11-Jan-86 | [1.296] No longer avoid getkey when running * 23-Jan-86 | [1.305] Introduce read_keyboard_char to handle cursor in * | non-mouse mode * 23-Jan-86 | [1.306] Recognize ^C in scan loop * 24-Jan-86 | [1.306] clear_off when memory data enter button hit * 25-Jan-86 | [1.328] New screen format; major rewrite * 25-Jan-86 | [1.347] Added code for alter-plus-one * 23-Feb-86 | [1.367] Color support. printfs go to scdspmsg * 23-Feb-86 | [1.367] include <> => include "" * 25-Feb-86 | [1.378] Use row-specific colors for 1447 input mode. When we * | rediscover the colors used on the 1447 we will change the * | initialization for this * 29-Jul-86 | [1.385] Added C-P option to do screen dump * 31-Jul-86 | [1.405] Removed keyboard support to kbd.c * 31-Jul-86 | [1.405] Made char variables unsigned * 18-Aug-86 | [1.414] screen.h -> bscreen.h * 10-Nov-91 | [1.428] converted for Microsoft C 6.0 * 18-Nov-91 | [1.428] memory.h => mem1401.h, avoid ANSI name * 23-Nov-91 | [1.455] converted to support mappable screen chars * 23-Dec-91 | [1.522] added stack checking pragmas *****************************************************************************/ /***************************************************************************** 1401 Simulation Enter Switch Module This module handles the bit-pattern select and ENTER switch *****************************************************************************/ #include "stdio.h" #include "boolean.h" #include "btypes.h" #include "scdspmsg.h" #include "panel.h" #include "mem1401.h" #include "mach.h" #include "modes.h" #include "mouse.h" #include "keys.h" #include "hercules.h" #include "disp.h" #include "diag.h" #include "enter.h" #include "addr.h" #include "display.h" #include "kb.h" #include "scan.h" #include "color.h" #include "bcd.h" #include "kbd.h" #include "1401.h" #include "button.h" #include "enter.h" #include "pause.h" #include "chars.h" unsigned char bcd_enter_char = '\0'; extern int current_mode; extern boolean mousing; extern int lastkey; extern boolean tracking; extern boolean color_printer; coord select_zones = 0; coord select_numeric = 0; boolean alter_plus_one = false; #define debug_xy true attrib row_colors[4]; /**************************************************************************** * get_enter_address * Result: int * Place to enter data ****************************************************************************/ int get_enter_address() { if(alter_plus_one) return B_addr++; return get_address_switches(); } /**************************************************************************** * mark_WM * Inputs: * boolean set: true to highlight, false to unhighlight * Effect: * Marks the WM enter button as appropriate ****************************************************************************/ void mark_WM(boolean set) { mark_screen(enter_X+1,enter_Y+4," ",set); mark_screen(enter_X+1,enter_Y+5,"WM",set); } /**************************************************************************** * mark_NWM * Inputs: * boolean set: true to highlight, false to unhighlight * Effect: * Marks the ~WM enter button as appropriate ****************************************************************************/ void mark_NWM(boolean set) { mark_screen(enter_X+1,enter_Y+1,"__",set); mark_screen(enter_X+1,enter_Y+2,"WM",set); } /**************************************************************************** * draw_enter_box * Effect: * Draws the 'enter' key box on the screen ****************************************************************************/ void draw_enter_box() { attrib fore; attrib back; if(ismono()) { /* mono */ fore = H_NORMAL; back = 0; } /* mono */ else { /* color */ fore = COLOR_LTBLUE; back = COLOR_BLACK; } /* color */ scdspmsg(enter_Y,enter_X,fore,back, "ษออป"); scdspmsg(enter_Y+1,enter_X,fore,back,"บ__บ"); scdspmsg(enter_Y+2,enter_X,fore,back,"บWMบ"); scdspmsg(enter_Y+3,enter_X,fore,back,"ฬออน"); scdspmsg(enter_Y+4,enter_X,fore,back,"บ บ"); scdspmsg(enter_Y+5,enter_X,fore,back,"บWMบ"); scdspmsg(enter_Y+6,enter_X,fore,back,"ศออผ"); mark_WM(false); mark_NWM(false); } /**************************************************************************** * draw_bit_box * Effect: * Draws the bit pattern select box on the screen ****************************************************************************/ void draw_bit_box() { attrib fore; attrib back; attrib d_back; attrib h_fore; attrib h_back; if(ismono()) { /* mono */ fore = H_NORMAL; back = 0; h_fore = H_NORMAL; h_back = 0; row_colors[0] = row_colors[1] = row_colors[2] = row_colors[3] = H_NORMAL; d_back = 0; } /* mono */ else { /* color */ fore = COLOR_LTBLUE; back = COLOR_BLACK; row_colors[0] = COLOR_WHITE; row_colors[1] = COLOR_WHITE; row_colors[2] = COLOR_WHITE; row_colors[3] = COLOR_WHITE; d_back = COLOR_BLACK; h_fore = legend_fore; h_back = legend_back; } /* color */ scdspmsg(pattern_Y,pattern_X,fore,back, "ึฤฤฤ ฤฤฤท"); scdspmsg(pattern_Y+1,pattern_X,fore,back,"ฬอออหออออออออออออออออออน"); scdspmsg(pattern_Y+2,pattern_X,fore,back,"บ บ บ"); scdspmsg(pattern_Y+3,pattern_X,fore,back,"บ บ บ"); scdspmsg(pattern_Y+4,pattern_X,fore,back,"บ บ บ"); scdspmsg(pattern_Y+5,pattern_X,fore,back,"บ บ บ"); scdspmsg(pattern_Y+6,pattern_X,fore,back,"ศอออสออออออออออออออออออผ"); scdspmsg(pattern_Y,pattern_X+4,h_fore,h_back,"Character Select"); { char tmp[20]; sprintf(tmp," 1234567890%c%c:>%c",char_equal,char_quote,char_sq); scdspmsg(pattern_Y+2,pattern_X+6,row_colors[0],d_back,tmp); sprintf(tmp,"%cABCDEFGHI?.%c[<%c",char_plus,char_rparen,char_gm); scdspmsg(pattern_Y+3,pattern_X+6,row_colors[1],d_back,tmp); sprintf(tmp,"-JKLMNOPQR!$*];%c",char_dl); scdspmsg(pattern_Y+4,pattern_X+6,row_colors[2],d_back,tmp); sprintf(tmp,"b/STUVWXYZ%c,%c%c\\%c",char_lparen,char_rm,char_wm,char_sm); scdspmsg(pattern_Y+5,pattern_X+6,row_colors[3],d_back,tmp); } scdspmsg(pattern_Y+2,pattern_X+2,row_colors[0],d_back,"NO"); scdspmsg(pattern_Y+3,pattern_X+2,row_colors[1],d_back,"BA"); scdspmsg(pattern_Y+4,pattern_X+2,row_colors[2],d_back," B"); scdspmsg(pattern_Y+5,pattern_X+2,row_colors[3],d_back," A"); } /**************************************************************************** * mark_column * Inputs: * coord col: Column to mark, 0..15 * boolean set: Value to set it to * Effect: * Marks the character selection dial column to the value indicated ****************************************************************************/ void mark_column(coord col,boolean set) { coord i; for(i=0;i<4;i++) { /* mark it */ markscreen((coord)(pattern_Y+2+i),(coord)(pattern_X+6+col),set, COLOR_BLACK,COLOR_WHITE,row_colors[i],COLOR_BLACK); } /* mark it */ } /**************************************************************************** * mark_row * Inputs: * coord row: Column to mark, 0..3 * boolean set: Value to set it to * Effect: * Marks the zone selection dial row to the value indicated ****************************************************************************/ void mark_row(coord row,boolean set) { coord i; for(i=0;i<3;i++) { /* mark it */ markscreen((coord)(pattern_Y+2+row),(coord)(pattern_X+1+i),set, COLOR_BLACK,COLOR_WHITE,row_colors[i],COLOR_BLACK); } /* mark it */ } /**************************************************************************** * show_selection * Effect: * Marks the selection ****************************************************************************/ void show_selection() { mark_column(select_numeric,true); mark_row(select_zones,true); } /**************************************************************************** * draw_enter_stuff * Effect: * Draws all the boxes for the enter mechanism ****************************************************************************/ void draw_enter_stuff() { draw_enter_box(); draw_bit_box(); show_selection(); } /**************************************************************************** * select_zone * Inputs: * coord X: Screen X-coordinate of mouse hit * coord Y: Screen Y-coordinate of mouse hit * Effect: * Snaps the mouse cursor to the zone selection dial, then * tracks the mouse up or down until the button is released ****************************************************************************/ void select_zone(coord X,coord Y) { short M1, M2, M3, M4; coord wY; /* Snap row */ mouse_coord minX; /* minimum X position */ mouse_coord minY; /* minimum Y position */ mouse_coord maxX; /* maximum X position */ mouse_coord maxY; /* maximum Y position */ mouse_coord cX; /* current X position */ mouse_coord cY; /* current Y position */ short VM2; /* virtual mouse (cursor arrow simulation */ boolean changed; /* change flag */ /* Snap mouse cursor to wheel position */ wY = pattern_Y + 2 + select_zones; M1 = mouse_set_cursor; M2 = 0; M3 = screen_to_mouse_x(X); M4 = screen_to_mouse_y(wY); vmouse(&M1,&M2,&M3,&M4); /* Now drag the lit row up and down with the mouse */ cX = M3; cY = M4; minY = screen_to_mouse_y(pattern_Y + 2); maxY = screen_to_mouse_y(pattern_Y + 5); minX = screen_to_mouse_x(pattern_X + 1); maxX = screen_to_mouse_x(pattern_X + 3); if(lastkey != KEYACTIVATE) VM2 = 0; /* no virtual mouse */ else VM2 = MOUSEACTIVATE; while(true) { /* track it */ lastkey = 0; /* read the cursor position */ get_keyboard_char(current_kb); /* lastkey may be zero, but we need to see motion */ M1 = mouse_get_cursor; vmouse(&M1,&M2,&M3,&M4); if(lastkey != 0) { /* keys */ if(lastkey == KEYACTIVATE2) M2 = VM2 = 0; /* simulate release of mouse key */ } /* keys */ else if(VM2!=0) M2 = VM2; if(tracking) { /* report motion */ trackit("zon",M2,M3,M4); pause(100); } /* report motion */ if((M2 & 7) == 0) break; /* button released */ /* Don't let it drag outside the valid columns */ changed = false; if(M3 < minX) { M3 = minX; changed = true;} else if(M3 > maxX) { M3 = maxX; changed = true;} if(M4 < minY) { M4 = minY; changed = true;} else if(M4 > maxY) { M4 = maxY; changed = true;} /* Set the cursor in case the above code did a limit operation */ if(changed) { /* fix change */ M1 = mouse_set_cursor; vmouse(&M1,&M2,&M3,&M4); } /* fix change */ /* Did we move at all? */ if(M4 == cY) continue; /* no X-motion, continue */ /* We have changed rows */ mark_row(mouse_to_screen_y(cY-minY),false); mark_row(mouse_to_screen_y(M4-minY),true); cY = M4; select_zones = mouse_to_screen_y(M4 - minY); } /* track it */ /* Now put the cursor back where we found it */ M1 = mouse_set_cursor; M3 = screen_to_mouse_x(X); M4 = screen_to_mouse_y(Y); vmouse(&M1,&M2,&M3,&M4); } /**************************************************************************** * select_char * Inputs: * coord X: Screen X-coordinate of mouse hit * coord Y: Screen Y-coordinate of mouse hit * Effect: * Snaps the mouse cursor to the character selection dial, then * tracks the mouse left or right until the button is released ****************************************************************************/ void select_char(coord X,coord Y) { short M1, M2, M3, M4; coord wX; /* Snap column */ mouse_coord minX; /* minimum X position */ mouse_coord minY; /* minimum Y position */ mouse_coord maxX; /* maximum X position */ mouse_coord maxY; /* maximum Y position */ mouse_coord cX; /* current X position */ mouse_coord cY; /* current Y position */ short VM2; /* virtual mouse (cursor arrow simulation */ boolean changed; /* change flag */ /* Snap mouse cursor to wheel position */ wX = pattern_X + 6 + select_numeric; M1 = mouse_set_cursor; M2 = 0; M3 = screen_to_mouse_x(wX); M4 = screen_to_mouse_y(Y); vmouse(&M1,&M2,&M3,&M4); /* Now drag the lit column back and forth with the mouse */ cX = M3; cY = M4; minY = screen_to_mouse_y(pattern_Y + 1); maxY = screen_to_mouse_y(pattern_Y + 6); minX = screen_to_mouse_x(pattern_X + 6); maxX = screen_to_mouse_x(pattern_X + 21); if(lastkey != KEYACTIVATE) VM2 = 0; /* no virtual mouse */ else VM2 = MOUSEACTIVATE; while(true) { /* track it */ lastkey = 0; /* read the cursor position */ get_keyboard_char(current_kb); /* lastkey may be zero, but we need to see motion */ M1 = mouse_get_cursor; vmouse(&M1,&M2,&M3,&M4); if(lastkey != 0) { /* keys */ if(lastkey == KEYACTIVATE2) M2 = VM2 = 0; /* release key */ } /* keys */ else if(VM2!=0) M2 = VM2; if(tracking) { /* report motion */ trackit("num",M2,M3,M4); pause(100); } /* report motion */ if((M2 & 7) == 0) break; /* button released */ /* Don't let it drag outside the valid columns */ changed = false; if(M3 < minX) { M3 = minX; changed = true;} else if(M3 > maxX) { M3 = maxX; changed = true; } if(M4 < minY) { M4 = minY; changed = true; } else if(M4 > maxY) { M4 = maxY; changed = true; } /* Set the cursor in case the above code did a limit operation */ if(changed) { /* fix change */ M1 = mouse_set_cursor; vmouse(&M1,&M2,&M3,&M4); } /* fix change */ /* Did we move at all? */ if(M3 == cX) continue; /* no X-motion, continue */ /* We have changed columns */ mark_column(mouse_to_screen_x(cX-minX),false); mark_column(mouse_to_screen_x(M3-minX),true); cX = M3; select_numeric = mouse_to_screen_x(M3 - minX); } /* track it */ /* Now put the cursor back where we found it */ M1 = mouse_set_cursor; M3 = screen_to_mouse_x(X); M4 = screen_to_mouse_y(Y); vmouse(&M1,&M2,&M3,&M4); } /**************************************************************************** * check_pattern_hit * Inputs: * coord X: X-screen coordinate of mouse hit * coord Y: Y-screen coordinate of mouse hit * Effect: * Flips the pattern bit if there is a hit ****************************************************************************/ void check_pattern_hit(coord X,coord Y) { /* See if we are anywhere in the character box. If so, we will do a move of the character wheel */ if(bounded(X,Y,pattern_X+5,pattern_Y+1,pattern_X+23,pattern_Y+6)) { /* hit in it somewhere */ clear_off(); hide_mouse_cursor(); select_char(X,Y); show_mouse_cursor(); } /* hit in it somewhere */ else /* See if we are anywhere in the zone box. If so, we will do a move of the zone wheel */ if(bounded(X,Y,pattern_X,pattern_Y+1,pattern_X+3,pattern_Y+6)) { /* hit in it somewhere */ clear_off(); hide_mouse_cursor(); select_zone(X,Y); show_mouse_cursor(); } /* hit in it somewhere */ bcd_enter_char = select_numeric; switch(select_zones) { /* cases */ case 0: /* none */ break; case 1: /* AB */ bcd_enter_char |= BA_bits; break; case 2: /* B */ bcd_enter_char |= B_bits; break; case 3: /* A */ bcd_enter_char |= A_bits; break; } /* cases */ } /**************************************************************************** * check_enter_switch * Inputs: * coord X: screen X position of mouse hit * coord Y: screen Y position of mouse hit * Result: boolean * true if a deposit was done * false if not * Effect: * If either the WM or ~WM switch has been hit, store the selected * character at the address indicated by the manual address switches * * Update the address display (but change no registers) to show the * address * * If the mouse right button is clicked, go into enter-plus-one mode ****************************************************************************/ boolean enter_plus_one = false; boolean check_enter_switch(coord X,coord Y) { short addr; /* The 'enter' switch is operable only in 'alter' mode */ if(current_mode != mode_alter) { /* can't alter unless in right mode */ return false; } /* can't alter unless in right mode */ if(bounded(X,Y,enter_X,enter_Y+4,enter_X+3,enter_Y+6)) { /* store WM */ clear_off(); mark_WM(true); addr = get_enter_address(); display_address(addr); if(diagnostics_on) { /* log it */ char msg[80]; sprintf(msg,"Store WM: location %d, char '%c'", addr,bcd_to_ascii(bcd_enter_char)); log_console_event(msg); } /* log it */ memory[addr] = bcd_enter_char | word_mark; wait_for_mouse_up(); mark_WM(false); return true; } /* store WM */ else if(bounded(X,Y,enter_X,enter_Y,enter_X+3,enter_Y+2)) { /* store ~WM */ clear_off(); mark_NWM(true); addr = get_enter_address(); display_address(addr); if(diagnostics_on) { /* log it */ char msg[80]; sprintf(msg,"Store ~WM: location %d, char '%c'", addr,bcd_to_ascii(bcd_enter_char)); log_console_event(msg); } /* log it */ memory[addr] = bcd_enter_char; wait_for_mouse_up(); mark_NWM(false); return true; } /* store ~WM */ return false; } /**************************************************************************** * cancel_alter_plus_one * Effect: * alter_plus_one mode is cancelled ****************************************************************************/ #pragma check_stack(off) void cancel_alter_plus_one() { alter_plus_one = false; } #pragma check_stack(on) /**************************************************************************** * check_alter_plus_one * Effect: * If the ACTIVATE2 button is pressed while dragging the cursor, * enter alter_plus_one mode * Note that this is the simulation of the the 1401 mode of * hit-the-start-button-while-holding-the-enter-key ****************************************************************************/ void check_alter_plus_one() { short M1, M2, M3, M4; if(!mousing) return; while(true) { /* scan mouse */ M1 = mouse_get_cursor; vmouse(&M1,&M2,&M3,&M4); if((M2 & 7) == 0) return; /* button up with no change */ #define PLUSONE (MOUSEACTIVATE | MOUSEACTIVATE2) if((M2 & PLUSONE ) == PLUSONE) { /* see if alter + 1 */ if(check_enter_switch(mouse_to_screen_x(M3),mouse_to_screen_y(M4))) { /* hit enter */ alter_plus_one = true; B_addr++; } /* hit enter */ } /* see if alter + 1 */ } /* scan mouse */ }