% idea: keep track of math style in integer parameter
% \mathstyle *while scanning the formula*. To be able 
% to do this, we need to keep track of
%
% \overline
% ^
% _
% \mathaccent
% style atoms
% \fraction{...\over...}
%
% Change necessary: \mathstyle is *not* an ordinary
% integer parameter, since math style doesn't obey
% grouping. Try ${\scriptscriptstyle 1}2$.
% Therefore it should be a special readonly parameter and
% a \cramp primitive should be separately added.

@x l.8392
@d input_line_no_code=glue_val+1 {code for \.{\\inputlineno}}
@d badness_code=glue_val+2 {code for \.{\\badness}}
@y
@d input_line_no_code=glue_val+1 {code for \.{\\inputlineno}}
@d badness_code=glue_val+2 {code for \.{\\badness}}
@d math_style_code=glue_val+3 {code for \.{\\mathstyle}}
@z

@x l.8420
primitive("badness",last_item,badness_code);
@!@:badness_}{\.{\\badness} primitive@>
@y
primitive("badness",last_item,badness_code);
@!@:badness_}{\.{\\badness} primitive@>
primitive("mathstyle",last_item,math_style_code);
@!@:mathstyle_}{\.{\\mathstyle} primitive@>
@z

@x l.8435
  input_line_no_code: print_esc("inputlineno");
  othercases print_esc("badness")
@y
  input_line_no_code: print_esc("inputlineno");
  badness_code: print_esc("badness");
  math_style_code: print_esc("mathstyle");
  othercases confusion("last_item")
@:this can't happen last_item}{\quad last_item@>
@z

%
% \mathstyle returns -1 if used outside math mode. 
%

@x l.8504
if cur_chr>glue_val then
  begin if cur_chr=input_line_no_code then cur_val:=line
  else cur_val:=last_badness; {|cur_chr=badness_code|}
  cur_val_level:=int_val;
  end
@y
if cur_chr>glue_val then
  begin if cur_chr=input_line_no_code then cur_val:=line
  else if cur_chr=math_style_code then begin 
    if abs(mode)=mmode then cur_val:=mathstyle
    else cur_val:=-1;
  end else cur_val:=last_badness;
  cur_val_level:=int_val;
  end
@z

@x l.14108
@!cur_style:small_number; {style code at current place in the list}
@y
@!cur_style,mathstyle:small_number; {style code at current place in the list}
@z

@x l.21649
begin push_math(math_shift_group); eq_word_define(int_base+cur_fam_code,-1);
if every_math<>null then begin_token_list(every_math,every_math_text);
@y
begin mathstyle:=text_style; 
push_math(math_shift_group); eq_word_define(int_base+cur_fam_code,-1);
if every_math<>null then begin_token_list(every_math,every_math_text);
@z

@x l.21700
push_math(math_shift_group); mode:=mmode;
eq_word_define(int_base+cur_fam_code,-1);@/
@y
mathstyle:=display_style;
push_math(math_shift_group); mode:=mmode;
eq_word_define(int_base+cur_fam_code,-1);@/
@z

@x l.21798
mmode+left_brace: begin tail_append(new_noad);
  back_input; scan_math(nucleus(tail));
@y
mmode+left_brace: begin tail_append(new_noad);
  back_input; scan_math(nucleus(tail),mathstyle);
@z

%
% we change scan_math to expect one additional parameter, 
% the mathstyle for the next math atom. There are two
% cases here:
% - simple atom: use local var stack to hold old style
%                and restore it from there
% - subformula:  use save stack to hold old style and
%                restore it when reading `}' 
%

@x l.21810
procedure scan_math(@!p:pointer);
label restart,reswitch,exit;
var c:integer; {math character code}
begin restart:@<Get the next non-blank non-relax...@>;
reswitch:case cur_cmd of
letter,other_char,char_given: begin c:=ho(math_code(cur_chr));
    if c=@'100000 then
      begin @<Treat |cur_chr| as an active character@>;
      goto restart;
      end;
    end;
char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
  goto reswitch;
  end;
math_char_num: begin scan_fifteen_bit_int; c:=cur_val;
  end;
math_given: c:=cur_chr;
delim_num: begin scan_twenty_seven_bit_int; c:=cur_val div @'10000;
  end;
othercases @<Scan a subformula enclosed in braces and |return|@>
endcases;@/
math_type(p):=math_char; character(p):=qi(c mod 256);
if (c>=var_code)and fam_in_range then fam(p):=cur_fam
else fam(p):=(c div 256) mod 16;
exit:end;
@y
procedure scan_math(@!p:pointer;s:small_number);
label restart,reswitch,exit;
var c:integer; {math character code}
  savedstyle:small_number;
begin 
savedstyle:=mathstyle; mathstyle:=s;
restart:@<Get the next non-blank non-relax...@>;
reswitch:case cur_cmd of
letter,other_char,char_given: begin c:=ho(math_code(cur_chr));
    if c=@'100000 then
      begin @<Treat |cur_chr| as an active character@>;
      goto restart;
      end;
    end;
char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
  goto reswitch;
  end;
math_char_num: begin scan_fifteen_bit_int; c:=cur_val;
  end;
math_given: c:=cur_chr;
delim_num: begin scan_twenty_seven_bit_int; c:=cur_val div @'10000;
  end;
othercases @<Scan a subformula enclosed in braces and |return|@>
endcases;@/
math_type(p):=math_char; character(p):=qi(c mod 256);
if (c>=var_code)and fam_in_range then fam(p):=cur_fam
else fam(p):=(c div 256) mod 16;
mathstyle:=savedstyle;
exit:
end;
@z

@x l.21848
begin back_input; scan_left_brace;@/
saved(0):=p; incr(save_ptr); push_math(math_group); return;
@y
begin back_input; scan_left_brace;@/
saved(0):=p; incr(save_ptr); saved(0):=savedstyle; incr(save_ptr);
push_math(math_group); return;
@z

@x l.21944
mmode+math_comp: begin tail_append(new_noad);
  type(tail):=cur_chr; scan_math(nucleus(tail));
@y
mmode+math_comp: begin tail_append(new_noad);
  type(tail):=cur_chr; 
  case type(tail) of
  over_noad: scan_math(nucleus(tail),cramped_style(mathstyle));
  othercases scan_math(nucleus(tail),mathstyle);
  endcases;
@z

%@x l.21999
%scan_delimiter(left_delimiter(tail),true); 
%if t=1 then scan_delimiter(right_delimiter(tail),true)
%else mem[right_delimiter(tail)].qqqq:=null_delimiter;
%scan_math(nucleus(tail));
%end;
%@y
%scan_delimiter(left_delimiter(tail),true); 
%if t=1 then scan_delimiter(right_delimiter(tail),true)
%else mem[right_delimiter(tail)].qqqq:=null_delimiter;
%scan_math(nucleus(tail),cramped_style(mathstyle));
%end;
%@z

@x
{before |scan_math| in |math_radical|}
scan_math(nucleus(tail)); 
@y
{before |scan_math| in |math_radical|}
scan_math(nucleus(tail),cramped_style(mathstyle));
@z

@x l.22012
if (cur_val>=var_code)and fam_in_range then fam(accent_chr(tail)):=cur_fam
else fam(accent_chr(tail)):=(cur_val div 256) mod 16;
scan_math(nucleus(tail));
end;
@y
if (cur_val>=var_code)and fam_in_range then fam(accent_chr(tail)):=cur_fam
else fam(accent_chr(tail)):=(cur_val div 256) mod 16;
scan_math(nucleus(tail),cramped_style(mathstyle));
end;
@z

@x l.22066
mmode+math_style: tail_append(new_style(cur_chr));
@y
mmode+math_style: begin tail_append(new_style(cur_chr));
  mathstyle:=cur_chr;
end;
@z

@x l.22076
procedure append_choices;
begin tail_append(new_choice); incr(save_ptr); saved(-1):=0;
push_math(math_choice_group); scan_left_brace;
@y
procedure append_choices;
begin tail_append(new_choice); 
incr(save_ptr); saved(-1):=mathstyle;
incr(save_ptr); saved(-1):=0;
push_math(math_choice_group); scan_left_brace;
mathstyle:=display_style;
@z

@x l.22094
3:begin script_script_mlist(tail):=p; decr(save_ptr); return;
  end;
end; {there are no other cases}
incr(saved(-1)); push_math(math_choice_group); scan_left_brace;
@y
3:begin script_script_mlist(tail):=p; decr(save_ptr); 
    mathstyle:=saved(-1); decr(save_ptr); 
    return;
  end;
end; {there are no other cases}
incr(saved(-1)); push_math(math_choice_group); scan_left_brace;
mathstyle:=2*saved(-1);
@z

@x l.22109
procedure sub_sup;
var t:small_number; {type of previous sub/superscript}
@!p:pointer; {field to be filled by |scan_math|}
begin t:=empty; p:=null;
if tail<>head then if scripts_allowed(tail) then
  begin p:=supscr(tail)+cur_cmd-sup_mark; {|supscr| or |subscr|}
  t:=math_type(p);
  end;
if (p=null)or(t<>empty) then @<Insert a dummy noad to be sub/superscripted@>;
scan_math(p);
end;
@y
procedure sub_sup;
var t:small_number; {type of previous sub/superscript}
@!p:pointer; {field to be filled by |scan_math|}
begin t:=empty; p:=null;
if tail<>head then if scripts_allowed(tail) then
  begin p:=supscr(tail)+cur_cmd-sup_mark; {|supscr| or |subscr|}
  t:=math_type(p);
  end;
if (p=null)or(t<>empty) then @<Insert a dummy noad to be sub/superscripted@>;
if cur_cmd=sup_mark then scan_math(p,sup_style(mathstyle))
else scan_math(p,sub_style(mathstyle));
end;
@z

@x l.22149
@d delimited_code=3 { `\.{\\abovewithdelims}', etc.}
@y
@d delimited_code=3 { `\.{\\abovewithdelims}', etc.}
@d fraction_code=6 { `\.{\\fraction}', etc.}
@z

@x l.22162
primitive("atopwithdelims",above,delimited_code+atop_code);
@!@:atop_with_delims_}{\.{\\atopwithdelims} primitive@>
@y
primitive("atopwithdelims",above,delimited_code+atop_code);
@!@:atop_with_delims_}{\.{\\atopwithdelims} primitive@>
primitive("fraction",above,fraction_code);
@!@:fraction_}{\.{\\fraction} primitive@>
@z

@x l.22171
  delimited_code+atop_code:print_esc("atopwithdelims");
  othercases print_esc("above")
@y
  delimited_code+atop_code:print_esc("atopwithdelims");
  fraction_code:print_esc("fraction");
  othercases print_esc("above")
@z

% We handle \fraction{...\over...} here, by scanning away
% the left brace and then doing the same as for 
% mmode+left_brace
% The point is that we have a handle to update the
% math_style variable properly here.
% We do scan_left_brace followed by back_input to
% force the left brace to be there

@x l.22176
mmode+above: math_fraction;
@y
mmode+above: if cur_chr=fraction_code then begin
  scan_left_brace; tail_append(new_noad);
  back_input;
  scan_math(nucleus(tail),num_style(mathstyle));
end else begin 
  math_fraction;
end;
@z

@x
procedure math_fraction;
var c:small_number; {the type of generalized fraction we are scanning}
begin c:=cur_chr;
@y
procedure math_fraction;
var c:small_number; {the type of generalized fraction we are scanning}
begin c:=cur_chr;
mathstyle:=denom_style(save_stack[cur_boundary-1].int);
@z

@x l.22258
math_group: begin unsave; decr(save_ptr);@/
  math_type(saved(0)):=sub_mlist; p:=fin_mlist(null); info(saved(0)):=p;
@y
math_group: begin unsave; decr(save_ptr);@/ 
  mathstyle:=saved(0); decr(save_ptr);
  math_type(saved(0)):=sub_mlist; p:=fin_mlist(null); info(saved(0)):=p;
@z