static void country_by_continent_box(GtkWidget *widget);
static void country_by_zone_box(GtkWidget *widget);
static void prefix_box(GtkWidget *widget);
static void help_box(GtkWidget *widget);
static void info6_box(GtkWidget *widget);
static void locus_box(GtkWidget *widget);
static void zone6_box(GtkWidget *widget);
static void who_box(GtkWidget *widget, gint idraw);
static void on_off_box(GtkWidget *widget);
static void capnum_lock_box(GtkWidget *widget, gint cn);
static void packet_box(GtkWidget *widget, gint idraw, gint from_radio);
static gint sort_bmap_lines(gchar bmap_lines[][22], gint bmap_num);
static void creader_volume_box(GtkWidget *widget, gint idraw);
static void creader_tuning_box(GtkWidget *widget, gint idraw);
static void creader_speed_box(GtkWidget *widget, gint idraw);
static void creader_box(GtkWidget *widget, gint idraw);
static gint start_creader(void);
static void stop_creader(void);
static void fill_creader_array(void);

static void country_by_continent_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, mb, country_color;
  gchar title[81], msg[18];
  gint jcol=-8, ic=0;
  gint row1=4, col1=1, row2=17, col2=80;
  const gchar *subtitle = "Previous/Next Continent:PgUp/PgDn";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  switch (isel_contest)
   {
    case DX :
    case WPX :
    case WW :
     mb = iband;
     strcpy(msg, " on Current Band)");
     break;
    case A160 :
     mb = mode;
     strcpy(msg, ")");
     break;
    case TEN :
     mb = mode;
     strcpy(msg, " on Current Mode)");
     break;
   }
  strcpy(title, "Countries in ");
  strcat(title, continent_names[ipage_screen[0][idisplay_type]]);
  strcat(title, " (Highlighted Entries are Needed");
  strcat(title, msg);
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, RED, SAVEPIX);
  for(i=0; i<=countries.number_of_countries; i++)
   if(!strcmp(countries.continent_abv[i],
      continent_abvs[ipage_screen[0][idisplay_type]]) &&
      countries.country_abv[i][0]!='+')
    {
     ii = ic%12;
     if(!ii) jcol+=11;
     ic++;
     if(countries.icountry_worked[mb][i])
      country_color = BLACK;
     else
      country_color = WHITE;
     write_line (row1+ii, jcol, countries.country_abv[i],
                 country_color, SAVEPIX);
    }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void country_by_zone_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, mb, izone, country_color, title_color;
  gchar title[81], zn0_char[3], zn_char[3];
  gint jcol=-8, ic=0;
  gint row1=4, col1=1, row2=10, col2=80;
  const gchar *subtitle = "Zone:#   Previous/Next Zone:PgUp/PgDn";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;

  izone = ipage_screen[0][idisplay_type];
  mb = iband;
  strcpy(zn0_char, zone_chars[izone]);
  if(zn0_char[0]==' ')
   zn0_char[0] = '0';
  strcpy(zn_char, zone_chars[izone]);
  left_blank_unpad (zn_char);
  strcpy(title, "Zone ");
  strcat(title, zn_char);
  if(!izone)
   title_color = WHITE;
  else if(!countries.izone_worked[mb][izone])
   {
    title_color = YELLOW;
    strcat(title,
     " is Needed (Highlighted Entries are Needed on Current Band)");
   }
  else
   {
    title_color = WHITE;
    strcat(title,
     " has been Worked (Highlighted Entries are Needed on Current Band)");
   }
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, title_color, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, RED, SAVEPIX);
  for(i=0; i<=countries.number_of_countries; i++)
   if(kb_index (countries.zones_in_country[i], zn0_char)>-1 &&
      countries.country_abv[i][0]!='+')
    {
     ii = ic%5;
     if(!ii) jcol+=11;
     ic++;
     if(countries.icountry_worked[mb][i])
      country_color = BLACK;
     else
      country_color = title_color;
     write_line (row1+ii, jcol, countries.country_abv[i],
                 country_color, SAVEPIX);
    }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void prefix_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, i1, i2;
  gchar title[81], subtitle[81], page_char[3], npages_char[3];
  gint jcol=-3, ic=0;
  gint row1=4, col1=1, row2=17, col2=80;

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  ipage_screen[1][idisplay_type] = (px_tree.npx-1)/144;
  int_to_char (ipage_screen[0][idisplay_type]+1, page_char);
  int_to_char (ipage_screen[1][idisplay_type]+1, npages_char);
  strcpy(title, "Prefixes (Listed Entries Have Been Worked)     Page ");
  strcat(title, page_char);
  strcat(title, " of ");
  strcat(title, npages_char);
  if(ipage_screen[1][idisplay_type])
   strcpy(subtitle, "Previous/Next Page:PgUp/PgDn");
  else
   strcpy(subtitle, "");
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, RED, SAVEPIX);
  i1 = 144*(ipage_screen[0][idisplay_type])+1;
  i2 = px_tree.npx<144*(ipage_screen[0][idisplay_type]+1) ? px_tree.npx :
        144*(ipage_screen[0][idisplay_type]+1);
  for(i=i1; i<=i2; i++)
   {
    ii = ic%12;
    if(!ii) jcol+=6;
    ic++;
    write_line (row1+ii, jcol, px_tree.px_array[i], WHITE, SAVEPIX);
   }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void help_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, i1, i2;
  gchar title[81], page_char[3], npages_char[3];
  gint jcol=3;
  gint row1=4, col1=1, row2=17, col2=80;
  const gchar *subtitle = "Previous/Next Page:PgUp/PgDn";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  int_to_char (ipage_screen[0][idisplay_type]+1, page_char);
  int_to_char (ipage_screen[1][idisplay_type]+1, npages_char);
  strcpy(title, "Help     Page ");
  strcat(title, page_char);
  strcat(title, " of ");
  strcat(title, npages_char);
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, BLUE, SAVEPIX);
  i1 = 12*ipage_screen[0][idisplay_type];
  i2 = helpbv.nhl<12*(ipage_screen[0][idisplay_type]+1)-1 ? helpbv.nhl :
        12*(ipage_screen[0][idisplay_type]+1)-1;
  ii = -1;
  for(i=i1; i<=i2; i++)
   {
    ii++;
    write_line (row1+ii, jcol, helpbv.help_lines[i], WHITE, SAVEPIX);
   }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void super_partial_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  GPatternSpec *gps;
  gint i, ii, isa, j, ipf, ipl, mcol, mp, mp_prev, lcl;
  gint min_chars, idt_lsave, super_color[300];
  gint use_call_list;
  gchar title[81], subtitle[81], msg[23], page_char[2], npages_char[2];
  gchar pattern[16], super_array[300][14];
  gint jcol=-12, ic=0;
  gint row1=4, col1=1, row2=17, col2=80;

  if(!strcmp(set_screen_choices[10], "<2>") || ialt_p)
   min_chars = 2;
  else if(!strcmp(set_screen_choices[10], "<3>"))
   min_chars = 3;
  else
   min_chars = 14;
  if(!ireset_display)
   {
    ipage_screen[0][IDT_SUPER] = 0;
    ipage_screen[1][IDT_SUPER] = 0;
   }
  lcl = strlen(cr_array[icall_count+1].call);
  if(cbv.item!=FT_CALL || lcl<min_chars || iscroll_log!=icall_count)
   {
    if(ireset_display)
     {
      ireset_display = FALSE;
      update_display (widget, REDRAW);
     }
   }
  else
   {
    i = 0;
    isa = 0;
    j = 0;
    if(cr_array[icall_count+1].call[0]!='~')
     {
      strcpy(pattern, "*");
      strcat(pattern, cr_array[icall_count+1].call);
     }
    else
     {
      concat(pattern, cr_array[icall_count+1].call, 1, lcl-1, COPY);
     }
    if(cr_array[icall_count+1].call[lcl-1]!='~')
     strcat(pattern, "*");
    else
     pattern[strlen(pattern)-1] = '\0';
    gps = g_pattern_spec_new (pattern);
    while(isa<300 && (i<icall_count || j<clib.number_of_calls))
     {
      if(i<icall_count && j<clib.number_of_calls)
       {
        if(strcmp(cr_array[call_tree.sort_order[i+1]].call,
           clib.call[j])<0)
         use_call_list = TRUE;
        else if(!strcmp(cr_array[call_tree.sort_order[i+1]].call,
                clib.call[j]))
         {
          use_call_list = TRUE;
          j++;
         }
        else
         use_call_list = FALSE;
       }
      else if(i<icall_count)
       use_call_list = TRUE;
      else
       use_call_list = FALSE;
      if(use_call_list)
       {
        i++;
        if(g_pattern_match_string (gps,
           cr_array[call_tree.sort_order[i]].call))
         {
          if(isel_contest==SS)
           super_color[isa] = BLACK;
          else
           super_color[isa] = HI_CYAN;
          strcpy(super_array[isa],
                 cr_array[call_tree.sort_order[i]].call);
          if(iband==cr_array[call_tree.sort_order[i]].iband &&
           mode==cr_array[call_tree.sort_order[i]].mode)
           super_color[isa] = BLACK;
          while(!strcmp(cr_array[call_tree.sort_order[i]].call,
                cr_array[call_tree.sort_order[i+1]].call) &&
                i<icall_count)
           {
            i++;
            if(iband==cr_array[call_tree.sort_order[i]].iband &&
             mode==cr_array[call_tree.sort_order[i]].mode)
             super_color[isa] = BLACK;
           }
          isa++;
         }
       }
      else
       {
        if(g_pattern_match_string (gps, clib.call[j]))
         if(isel_contest!=DX ||
          (strcmp(clib.country[j], "W") && strcmp(clib.country[j], "VE")))
          {
           super_color[isa] = WHITE;
           strcpy(super_array[isa], clib.call[j]);
           isa++;
          }
        j++;
       }
     }
    g_pattern_spec_free (gps);
    if(isa)
     {
      update_rect.x = col1*wcol;
      update_rect.y = row1*hrow;
      update_rect.width = (col2-col1-1)*wcol;
      update_rect.height = (row2-row1-1)*hrow;
      switch (isel_contest)
       {
        case FD :
        case NYQP :
        case WAA :
         strcpy(msg, " on Current Band/Mode)");
         break;
        case DX :
        case WPX :
        case WW :
         strcpy(msg, " on Current Band)");
         break;
        case TEN :
         strcpy(msg, " on Current Mode)");
         break;
        default :
         strcpy(msg, ")");
       }
      strcpy(title, "Partials (Highlighted Calls are Needed");
      strcat(title, msg);
      strcpy(subtitle, "Select:Click   Load:Reclick");
      ipage_screen[1][IDT_SUPER] = (isa-1)/60;
      if(ipage_screen[1][IDT_SUPER])
       {
        int_to_char (ipage_screen[0][IDT_SUPER]+1, page_char);
        int_to_char (ipage_screen[1][IDT_SUPER]+1, npages_char);
        strcat(subtitle, "   Previous/Next Page:PgUp/PgDn     Page ");
        strcat(subtitle, page_char);
        strcat(subtitle, " of ");
        strcat(subtitle, npages_char);
       }
      ipf = ipage_screen[0][IDT_SUPER]*60;
      ipl = ipf+60<isa ? ipf+60 : isa;
      draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
                title, WHITE, subtitle, LT_GRAY, SAVEPIX);
      draw_rectangle (&update_rect, RED, SAVEPIX);
      for(i=ipf; i<ipl; i++)
       {
        ii = ic%12;
        if(!ii) jcol+=15;
        ic++;
        write_line (row1+ii, jcol, super_array[i],
                    super_color[i], SAVEPIX);
       }
      if(mcv.button && mcv.row>row1 && mcv.row<row2)
       {
        mp = ((mcv.col-2)/15)*12+mcv.row-row1;
        if(mp<=ipl-ipf)
         {
          mcol = ((mcv.col-2)/15)*15+1;
          write_line (mcv.row-1, mcol, "->", YELLOW, SAVEPIX);
          mp_prev = ((mcv.col_prev-2)/15)*12+mcv.row_prev-row1;
          if(mp==mp_prev)
           {
            strcpy(cr_array[icall_count+1].call, super_array[ipf+mp-1]);
            cbv.cursor_col = cbv.col1[FT_CALL]+
             strlen(cr_array[icall_count+1].call);
            ireset_display = FALSE;
            update_display (widget, REDRAW);
            return;
           }
         }
       }
      gtk_widget_queue_draw_area (widget,
                                  update_rect.x-wcol,
                                  update_rect.y-hrow,
                                  update_rect.width+2*wcol,
                                  update_rect.height+2*hrow);
      ireset_display = TRUE;
      idt_lsave = idisplay_type;
      idisplay_type = IDT_SUPER;
      message_box (widget, "", !REDRAW, !CLEAR);
      idisplay_type = idt_lsave;
     }
    else if(ireset_display)
     {
      ireset_display = FALSE;
      update_display (widget, REDRAW);
     }
   }
}

static void info6_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, mb, row2, imax;
  gint hd[2];
  gchar title[81], header_line[77], header_hold[39], bm_char[6], *inspt;
  gchar qso[12][5], day[12][4], utc[12][5], rec[12][8], dup[12][2];
  gint jcol=-46;
  gint row1=4, col1=1, col2=80;
  const gchar *subtitle = "";
  const gchar *header_dupes = "         Dupes       ";

  row2 = 22-log_lines[IDT_INFO6];
  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  for(i=0; i<12; i++)
   {
    strcpy(qso[i], "");
    strcpy(day[i], "");
    strcpy(utc[i], "");
    strcpy(rec[i], "");
    strcpy(dup[i], "");
   }
  hd[0] = 0;
  hd[1] = strlen(header_dupes)-1;
  switch (isel_contest)
   {
    case DX :
    case WPX :
    case WW :
    case SS :
     strcpy(title, "Six Band Qso Information");
     strcpy(header_hold, "Band  Qso  ^^^   Utc  Rcvd");
     break;
    case FD :
    case NYQP :
    case WAA :
     strcpy(title, "Six Band Qso Information");
     strcpy(header_hold, "Band/Mode  Qso  ^^^   Utc  Rcvd");
     hd[0] = 5;
     hd[1] -= 5;
     break;
    case A160 :
     strcpy(title, "Qso Information");
     strcpy(header_hold, "Mode  Qso  ^^^   Utc  Rcvd");
     break;
    case TEN :
     strcpy(title, "Two Mode Qso Information");
     strcpy(header_hold, "Mode  Qso  ^^^   Utc  Rcvd");
     break;
   }
  inspt = strstr(header_hold, "^^^");
  for(i=0; i<3; i++)
   {
    *inspt = month_array[kb_time.tm_mon][i];
    inspt++;
   }
  strcpy(header_line, header_hold);
  concat(header_line, header_dupes, hd[CW], hd[PH], !COPY);
  strcat(header_line, header_hold);
  draw_rectangle (&update_rect, RED, SAVEPIX);
  write_line (row1, col1+1, header_line, WHITE, SAVEPIX);
  write_line (row2-2, col1+1, header_line, WHITE, SAVEPIX);
  switch (log_lines[IDT_INFO6])
   {
    case 9 :
     imax = 12;
     for(i=0; i<imax; i++)
      {
       ii = i%6;
       if(!ii) jcol+=47;
       strcpy(bm_char, bandw[ii]);
       strcat(bm_char, mode_char[i/6]);
       write_line (row1+1+ii, col1+2-5*(i/6)+jcol, bm_char, WHITE, SAVEPIX);
      }
     break;
    case 12 :
     imax = 6;
     for(i=0; i<imax; i++)
      {
       ii = i%3;
       if(!ii) jcol+=47;
       write_line (row1+1+ii, col1+1+jcol, bandw[i], WHITE, SAVEPIX);
      }
     break;
    case 14 :
     imax = 2;
     for(i=0; i<imax; i++)
      {
       jcol+=47;
       write_line (row1+1, col1+1+jcol, mode_char[i], WHITE, SAVEPIX);
      }
     break;
   }
  for(i=0; i<row2-row1-3; i++)
   write_line (row1+1+i, (col1+col2)/2-1, "|", WHITE, SAVEPIX);
  if(call_tree.cmatch>0)
   {
    for(i=call_tree.clow; i<=call_tree.chigh; i++)
     {
      mb = cr_array[call_tree.sort_order[i]].mode*6+
           cr_array[call_tree.sort_order[i]].iband;
      if(!strcmp(cr_array[call_tree.sort_order[i]].dupe, "*"))
       {
        strcpy(dup[mb], "*");
        if(isel_contest==SS && !strlen(qso[mb]))
         {
          strcpy(qso[mb], cr_array[call_tree.sort_order[i]].qso);
          concat(day[mb], cr_array[call_tree.sort_order[i]].date,
                 2, 3, COPY);
          concat(utc[mb], cr_array[call_tree.sort_order[i]].time,
                 0, 3, COPY);
          strcpy(rec[mb], cr_array[call_tree.sort_order[i]].rec_num);
          strcat(rec[mb], cr_array[call_tree.sort_order[i]].tx);
          strcat(rec[mb], cr_array[call_tree.sort_order[i]].prefix);
         }
       }
      else
       {
        strcpy(qso[mb], cr_array[call_tree.sort_order[i]].qso);
        concat(day[mb], cr_array[call_tree.sort_order[i]].date,
               2, 3, COPY);
        concat(utc[mb], cr_array[call_tree.sort_order[i]].time,
               0, 3, COPY);
        strcpy(rec[mb], cr_array[call_tree.sort_order[i]].rec_num);
        if(isel_contest==SS)
         {
          strcat(rec[mb], cr_array[call_tree.sort_order[i]].tx);
          strcat(rec[mb], cr_array[call_tree.sort_order[i]].prefix);
         }
       }
     }
    jcol = -42+hd[0];
    for(i=0; i<imax; i++)
     {
      ii = i%(imax/2);
      if(!ii) jcol+=47;
      if(imax==2)
       mb = i*6+iband;
      else if(imax==6)
       mb = mode*6+i;
      else if(imax==12)
       mb = i;
      write_line (row1+1+ii, col1+1-hd[0]*(i/6)+jcol, qso[mb],
                  YELLOW, SAVEPIX);
      write_line (row1+1+ii, col1+8-hd[0]*(i/6)+jcol, day[mb],
                  YELLOW, SAVEPIX);
      write_line (row1+1+ii, col1+12-hd[0]*(i/6)+jcol, utc[mb],
                  YELLOW, SAVEPIX);
      write_line (row1+1+ii, col1+18-hd[0]*(i/6)+jcol, rec[mb],
                  YELLOW, SAVEPIX);
      write_line (row1+1+ii, (col1+col2)/2-2+2*((2*i)/imax), dup[mb],
                  YELLOW, SAVEPIX);
     }
    strcpy(title, cr_array[call_tree.sort_order[call_tree.clow]].call);
    strcat(title, " - ");
    strcat(title,
           cr_array[call_tree.sort_order[call_tree.clow]].rec_county);
   }
  else if(call_tree.cmatch<0 && strlen(cr_array[icall_count+1].call))
   {
    strcpy(title, cr_array[icall_count+1].call);
    strcat(title, " - ");
    strcat(title, "Has Not Been Worked");
   }
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, WHITE, subtitle, LT_GRAY, SAVEPIX);
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void locus_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, locus_color, j;
  gchar title[81];
  gint jcol=-11, jadd=14;
  gint row1=4, col1=1, row2=15, col2=80;
  const gchar *subtitle = "";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  switch (isel_contest)
   {
    case NYQP :
     if(strcmp(init_screen_choices[6], "NY"))
      strcpy(title, "Counties ");
     else
      strcpy(title, "Counties/States/Provinces ");
     strcat(title, "(Highlighted Entries are Needed)");
     break;
    case FD :
    case SS :
    case A160 :
     strcpy(title, "Sections (Highlighted Entries are Needed)");
     break;
    case TEN :
     strcpy(title, "States/Provinces (Highlighted Entries are Needed");
     strcat(title, " on Current Mode)");
     break;
    case WAA :
     strcpy(title, "States/Provinces (Highlighted Entries are Needed)");
     break;
   }
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, RED, SAVEPIX);
  if(loci.number_of_loci>60)
   {
    jcol = ((loci.number_of_loci-1)/10)-14;
    jadd = 17-(loci.number_of_loci-1)/10;
   }
  for(i=1; i<=loci.number_of_loci; i++)
   {
    ii = (i-1)%10+1;
    if(ii==1) jcol += jadd;
    switch (isel_contest)
     {
      case FD :
      case WAA :
       if(loci.locus_worked[6*mode+iband][i])
        locus_color = BLACK;
       else
        locus_color = WHITE;
       break;
      case NYQP :
       locus_color = WHITE;
       for(j=0; j<12; j++)
        if(loci.locus_worked[j][i])
         {
          locus_color = BLACK;
          break;
         }
       break;
      case SS :
       locus_color = WHITE;
       for(j=0; j<6; j++)
        if(loci.locus_worked[j][i])
         {
          locus_color = BLACK;
          break;
         }
       break;
      case A160 :
      case TEN :
       if(loci.locus_worked[mode][i])
        locus_color = BLACK;
       else
        locus_color = WHITE;
       break;
     }
    write_line (row1-1+ii, col1-1+jcol, loci.locus_abv[i],
                locus_color, SAVEPIX);
   }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void zone6_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint i, ii, mb, zone_color;
  gint jcol=-3, ic=0;
  gint row1=4, col1=1, row2=16, col2=80;
  const gchar *title = "Zones by Band (Highlighted Entries are Needed)";
  const gchar *subtitle = "";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
            title, WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, RED, SAVEPIX);
  for(mb=0; mb<6; mb++)
   {
    jcol++;
    write_line (row1, col1+5+mb*13, bandw[mb], YELLOW, SAVEPIX);
    for(i=1; i<MAX_ZONES; i++)
     {
      ii = ic%10;
      if(!ii) jcol+=3;
      ic++;
      if(countries.izone_worked[mb][i])
       zone_color = BLACK;
      else
       zone_color = WHITE;
      write_line (row1+ii+1, col1+jcol, zone_chars[i],
                  zone_color, SAVEPIX);
     }
   }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-wcol,
                              update_rect.y-hrow,
                              update_rect.width+2*wcol,
                              update_rect.height+2*hrow);
}

static void who_box(GtkWidget *widget, gint idraw)
{
  GdkRectangle update_rect, update_arrow;
  gint i, ii, isa, j, ipf, ipl, mcol, mp, mp_prev;
  gint who_color[300];
  gint use_call_list;
  gchar title[81], subtitle[81], page_char[2], npages_char[2];
  gchar who_array[300][14], lib_locus[5], msg[61];
  gint jcol=-12, ic=0, ivl=TRUE;
  gint row1=4, col1=1, row2=17, col2=80;

  if(idraw)
   {
    ipage_screen[0][IDT_WHO] = 0;
    ipage_screen[1][IDT_WHO] = 0;
   }
  if(!strlen(cr_array[icall_count+1].call))
   {
    idisplay_type = idt_save;
    play_bells (MESSAGE_SOUND);
    strcpy(msg, "Make an entry, then press ");
    if(!strcmp(set_screen_choices[11], "<YES>"))
     strcat(msg, "Shift-F7");
    else
     strcat(msg, "F7");
    message_box (widget, msg, REDRAW, CLEAR);
   }
  else
   {
    for(i=1; i<=loci.number_of_loci; i++)
     if(!strcmp(cr_array[icall_count+1].call, loci.locus_abv[i]))
      {
       ivl = FALSE;
       break;
      }
    if(ivl)
     {
      idisplay_type = IDT_LOCUS;
      update_display (widget, REDRAW);
      strcpy(msg, "Invalid entry! - ");
      strcat(msg, cr_array[icall_count+1].call);
      play_bells (BAD_KEY_SOUND);
      boxed_message (msg, 2000, LT_GRAY);
      return;
     }
    i = 0;
    isa = 0;
    j = 0;
    while(isa<300 && (i<icall_count || j<clib.number_of_calls))
     {
      if(i<icall_count && j<clib.number_of_calls)
       {
        if(strcmp(cr_array[call_tree.sort_order[i+1]].call,
           clib.call[j])<0)
         use_call_list = TRUE;
        else if(!strcmp(cr_array[call_tree.sort_order[i+1]].call,
                clib.call[j]))
         {
          use_call_list = TRUE;
          j++;
         }
        else
         use_call_list = FALSE;
       }
      else if(i<icall_count)
       use_call_list = TRUE;
      else
       use_call_list = FALSE;
      if(use_call_list)
       {
        i++;
        if(!strcmp(cr_array[icall_count+1].call,
           cr_array[call_tree.sort_order[i]].rec_county))
         {
          if(isel_contest==SS)
           who_color[isa] = BLACK;
          else
           who_color[isa] = HI_CYAN;
          strcpy(who_array[isa],
                 cr_array[call_tree.sort_order[i]].call);
          if(iband==cr_array[call_tree.sort_order[i]].iband &&
           mode==cr_array[call_tree.sort_order[i]].mode)
           who_color[isa] = BLACK;
          while(!strcmp(cr_array[call_tree.sort_order[i]].call,
                cr_array[call_tree.sort_order[i+1]].call) &&
                i<icall_count)
           {
            i++;
            if(iband==cr_array[call_tree.sort_order[i]].iband &&
             mode==cr_array[call_tree.sort_order[i]].mode)
             who_color[isa] = BLACK;
           }
          isa++;
         }
       }
      else
       {
        switch (isel_contest)
         {
          case FD :
          case SS :
          case A160 :
           strcpy(lib_locus, clib.section[j]);
           break;
          case TEN :
          case WAA :
           strcpy(lib_locus, clib.state[j]);
           break;
          case NYQP :
           strcpy(lib_locus, clib.county[j]);
           break;
          default :
           strcpy(lib_locus, "");
         }
        if(!strcmp(cr_array[icall_count+1].call, lib_locus))
         {
          who_color[isa] = WHITE;
          strcpy(who_array[isa], clib.call[j]);
          isa++;
         }
        j++;
       }
     }
    update_rect.x = col1*wcol;
    update_rect.y = row1*hrow;
    update_rect.width = (col2-col1-1)*wcol;
    update_rect.height = (row2-row1-1)*hrow;
    strcpy(title, "Stations in ");
    strcat(title, cr_array[icall_count+1].call);
    strcat(title, " (Highlighted Entries are Needed)");
    strcpy(subtitle, "Select:Click   Load:Reclick");
    ipage_screen[1][IDT_WHO] = (isa-1)/60;
    if(ipage_screen[1][IDT_WHO])
     {
      int_to_char (ipage_screen[0][IDT_WHO]+1, page_char);
      int_to_char (ipage_screen[1][IDT_WHO]+1, npages_char);
      strcat(subtitle, "   Previous/Next Page:PgUp/PgDn     Page ");
      strcat(subtitle, page_char);
      strcat(subtitle, " of ");
      strcat(subtitle, npages_char);
     }
    ipf = ipage_screen[0][IDT_WHO]*60;
    ipl = ipf+60<isa ? ipf+60 : isa;
    draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
              title, WHITE, subtitle, LT_GRAY, SAVEPIX);
    draw_rectangle (&update_rect, RED, SAVEPIX);
    for(i=ipf; i<ipl; i++)
     {
      ii = ic%12;
      if(!ii) jcol+=15;
      ic++;
      write_line (row1+ii, jcol, who_array[i], who_color[i], SAVEPIX);
     }
    if(mcv.button)
     {
      if(mcv.row_prev>row1 && mcv.row_prev<row2)
       {
        mcol = ((mcv.col_prev-2)/15)*15+1;
        update_arrow.x = mcol*wcol;
        update_arrow.y = (mcv.row_prev-1)*hrow;
        update_arrow.width = 2*wcol;
        update_arrow.height = hrow;
        draw_rectangle (&update_arrow, RED, SAVEPIX);
       }
      if(mcv.row>row1 && mcv.row<row2)
       {
        mp = ((mcv.col-2)/15)*12+mcv.row-row1;
        if(mp<=ipl-ipf)
         {
          mcol = ((mcv.col-2)/15)*15+1;
          write_line (mcv.row-1, mcol, "->", YELLOW, SAVEPIX);
          mp_prev = ((mcv.col_prev-2)/15)*12+mcv.row_prev-row1;
          if(mp==mp_prev)
           {
            strcpy(cr_array[icall_count+1].call, who_array[ipf+mp-1]);
            cbv.cursor_col = cbv.col1[FT_CALL]+
             strlen(cr_array[icall_count+1].call);
            cyan_bar (widget);
            update_arrow.x = mcol*wcol;
            update_arrow.y = (mcv.row-1)*hrow;
            update_arrow.width = 2*wcol;
            update_arrow.height = hrow;
            draw_rectangle (&update_arrow, RED, SAVEPIX);
            mcv.row = 0;
            mcv.col = 0;
            mcv.button = 0;
            idisplay_type = idt_save;
            update_display (widget, REDRAW);
            return;
           }
         }
        else
         {
          mcv.row = 0;
          mcv.col = 0;
          mcv.button = 0;
         }
       }
      else
       {
        mcv.row = 0;
        mcv.col = 0;
        mcv.button = 0;
       }
     }
    gtk_widget_queue_draw_area (widget,
                                update_rect.x-wcol,
                                update_rect.y-hrow,
                                update_rect.width+2*wcol,
                                update_rect.height+2*hrow);
   }
}

static void on_off_box(GtkWidget *widget)
{
  GdkRectangle update_rect;
  gint col1, col2, dsec, mm, ss;
  gchar dtc[6], mmc[3], ssc[3];
  gint row1=21, row2=23;
  const gchar *title = "";
  const gchar *subtitle = "";
  const gchar *msg[2] = {"Minimum time for an off-period",
                         "has elapsed - Kick Butt!"};
  static gint itip = TRUE;

  if(strcmp(cr_array[icall_count+1].on_off, on_off_char[2]))
   {
    itip = TRUE;
    return;
   }
  if(cbv.col1[FT_ONOFF])
   col1 = cbv.col1[FT_ONOFF]-3;
  else
   col1 = cbv.col1[FT_TIME]-3;
  col2 = col1+6;
  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  if(isel_contest==FD)
   dsec = 0;
  else
   {
    fill_cr_array_dt (6499);
    dsec = 60*atoi(set_screen_choices[9])-
           idelta_time (cr_array[icall_count].date, cr_array[6499].date,
                        cr_array[icall_count].time, cr_array[6499].time);
   }
  if(dsec>0 && dsec<3601)
   {
    mm = dsec/60;
    int_to_char (mm, mmc);
    left_zero_pad (mmc, sizeof(mmc));
    ss = dsec%60;
    int_to_char (ss, ssc);
    left_zero_pad (ssc, sizeof(ssc));
    strcpy(dtc, mmc);
    strcat(dtc, ":");
    strcat(dtc, ssc);
    draw_box (row1, col1, row2, col2, 1, BLACK, CYAN,
              title, WHITE, subtitle, LT_GRAY, !SAVEPIX);
    draw_rectangle (&update_rect, CYAN, !SAVEPIX);
    write_line (row1, col1, dtc, YELLOW, !SAVEPIX);
    if(itip)
     {
      tip_message (widget, TIP_TIMER);
      itip = FALSE;
     }
   }
  else
   {
    strcpy(cr_array[icall_count+1].on_off, on_off_char[1]);
    scroll_log (widget);
    cyan_bar (widget);
    message_box (widget, msg[1], !REDRAW, CLEAR);
    message_box (widget, msg[0], !REDRAW, !CLEAR);
    if(ireset_display)
     {
      ireset_display = FALSE;
      update_display (widget, REDRAW);
     }
    play_bells (MESSAGE_SOUND);
    itip = TRUE;
   }
}

static void capnum_lock_box(GtkWidget *widget, gint cn)
{
  GdkRectangle update_rect;
  gint box_color, msg_color;
  gint col1, col2;
  gint row1=21, row2=23;
  const gchar *title = "";
  const gchar *subtitle = "";
  const gchar *msg[2] = {"TURN OFF CAPS LOCK!!!", "TURN ON NUM LOCK!!!"};
  static gint invert=TRUE;

  col1 = cbv.col1[FT_CALL]-2;
  col2 = col1+strlen(msg[cn])+1;
  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  invert = !invert;
  if(invert)
   {
    box_color = HI_MAGENTA;
    msg_color = HI_BLUE;
   }
  else
   {
    box_color = HI_BLUE;
    msg_color = HI_MAGENTA;
   }
  draw_box (row1, col1, row2, col2, 1, BLACK, box_color,
            title, WHITE, subtitle, LT_GRAY, !SAVEPIX);
  draw_rectangle (&update_rect, box_color, !SAVEPIX);
  write_line (row1, col1, msg[cn], msg_color, !SAVEPIX);
}

static void packet_box(GtkWidget *widget, gint idraw, gint from_radio)
{
  GdkRectangle update_rect, update_arrow;
  gint i, mp, mp_prev, mcol, spot_color, ipci, mb, new_mult, unknown;
  gchar packet_rec_county[20], call_px[14], spot_freq[8], radio_freq[8];
  gchar spot_call[14];
  static gchar packet_bmap_lines[MAX_BMAP_LINES][22];
  static gint imin = 0;
  static gint imax = -1;
  gint ii=-1, idr=0, bmap_num=-1, ic=0, jcol=-21, spot_del=-1;
  gint row1=4, col1=1, row2=17, col2=80;
  gint packet_box_color[2] = {MID_GRAY, BLUE};
  gchar title[2][81] = {"Packet Terminal", ""};
  const gchar *subtitle[2] = {"Packet Bandmap:PgUp/PgDn",
   "Packet Terminal:PgUp/PgDn   New Band/Freq:Keypad Arrows   Refresh:Keypad 5"};

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  if(idraw)
   packet_band = iband;
  if(ipage_screen[0][idisplay_type])
   {
    strcpy(title[1], "Packet Bandmap for ");
    strcat(title[1], bandw[packet_band]);
    strcat(title[1], "M");
   }
  if(idraw || ipage_screen[0][idisplay_type])
   {
    idr = 1;
    if(packet_band==iband)
     draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
               title[ipage_screen[0][idisplay_type]], WHITE,
               subtitle[ipage_screen[0][idisplay_type]], LT_GRAY, SAVEPIX);
    else
     draw_box (row1, col1, row2, col2, 2, RED, BLACK,
               title[ipage_screen[0][idisplay_type]], HI_RED,
               subtitle[ipage_screen[0][idisplay_type]], RED, SAVEPIX);
    black_bar (widget, row1, col1-1, row2, col1-1);
   }
  switch (isel_contest)
   {
    case A160 :
    case TEN :
     mb = mode;
     break;
    default :
     mb = packet_band;
   }
  if(!ipage_screen[0][idisplay_type])
   {
    draw_rectangle (&update_rect,
     packet_box_color[ipage_screen[0][idisplay_type]], SAVEPIX);
    if(packet_num>-1)
     {
      for(i=packet_num+1; i<17-log_lines[IDT_PACKET]; i++)
       {
        ii++;
        write_line (row1+ii, 2, packet_array[i], WHITE, SAVEPIX);
       }
      for(i=0; i<=packet_num; i++)
       {
        ii++;
        write_line (row1+ii, 2, packet_array[i], WHITE, SAVEPIX);
       }
     }
   }
  else
   {
    if(mcv.button)
     {
      if(mcv.row_prev>row1 && mcv.row_prev<row2)
       {
        mcol = ((mcv.col_prev-2)/24)*24+1;
        update_arrow.x = mcol*wcol;
        update_arrow.y = (mcv.row_prev-1)*hrow;
        update_arrow.width = 2*wcol;
        update_arrow.height = hrow;
        draw_rectangle (&update_arrow,
         packet_box_color[ipage_screen[0][idisplay_type]], SAVEPIX);
       }
      if(mcv.row>row1 && mcv.row<row2)
       {
        mp = ((mcv.col-2)/24)*12+mcv.row-row1;
        if(mp<=imax-imin+1 && imax>-1)
         {
          mcol = ((mcv.col-2)/24)*24+1;
          if(mcv.button==1)
           write_line (mcv.row-1, mcol, "->", YELLOW, SAVEPIX);
          else
           write_line (mcv.row-1, mcol, "->", HI_RED, SAVEPIX);
          mp_prev = ((mcv.col_prev-2)/24)*12+mcv.row_prev-row1;
          if(mp==mp_prev)
           {
            if(mcv.button==mcv.button_prev)
             {
              if(mcv.button==1)
               {
                concat(cr_array[icall_count+1].call,
                 packet_bmap_lines[imin+mp-1],
                 8, strlen(packet_bmap_lines[imin+mp-1])-1, COPY);
                cbv.cursor_col = cbv.col1[FT_CALL]+
                 strlen(cr_array[icall_count+1].call);
                if(fp_radio)
                 {
                  concat(spot_freq, packet_bmap_lines[imin+mp-1], 0, 6, COPY);
                  process_frequency_command (spot_freq);
                  if(rcv.radio_split==SPLIT_ON)
                   {
                    change_radio_split (SPLIT_OFF);
                    message_box (widget, "Split is Off.", REDRAW, CLEAR);
                    play_bells (MESSAGE_SOUND);
                   }
                  update_display (widget, REDRAW);
                  return;
                 }
                else
                 {
                  cyan_bar (widget);
                  update_arrow.x = mcol*wcol;
                  update_arrow.y = (mcv.row-1)*hrow;
                  update_arrow.width = 2*wcol;
                  update_arrow.height = hrow;
                  draw_rectangle (&update_arrow,
                   packet_box_color[ipage_screen[0][idisplay_type]], SAVEPIX);
                 }
               }
              else
               {
                concat(spot_freq, packet_bmap_lines[imin+mp-1], 0, 6, COPY);
                concat(spot_call, packet_bmap_lines[imin+mp-1],
                 8, strlen(packet_bmap_lines[imin+mp-1])-1, COPY);
                for(i=pbm.spot_num; i>=0; i--)
                 {
                  if(!strcmp(pbm.frequency[i], spot_freq) &&
                     !strcmp(pbm.call[i], spot_call))
                   {
                    pbm.frequency[i][0] = '4';
                    spot_del = i;
                    break;
                   }
                 }
                if(spot_del==-1)
                 for(i=PBM_LINES-1; i>pbm.spot_num; i--)
                  {
                   if(!strcmp(pbm.frequency[i], spot_freq) &&
                      !strcmp(pbm.call[i], spot_call))
                    {
                     pbm.frequency[i][0] = '4';
                     spot_del = i;
                     break;
                    }
                  }
                update_display (widget, REDRAW);
                return;
               }
             }
            else
             {
              update_arrow.x = mcol*wcol;
              update_arrow.y = (mcv.row-1)*hrow;
              update_arrow.width = 2*wcol;
              update_arrow.height = hrow;
              draw_rectangle (&update_arrow,
               packet_box_color[ipage_screen[0][idisplay_type]], SAVEPIX);
             }
            mcv.row = 0;
            mcv.col = 0;
            mcv.button = 0;
           }
         }
        else
         {
          mcv.row = 0;
          mcv.col = 0;
          mcv.button = 0;
         }
       }
      else
       {
        mcv.row = 0;
        mcv.col = 0;
        mcv.button = 0;
       }
     }
    else if(from_radio)
     {
      for(i=imin; i<=imax; i++)
       {
        ii = ic%12;
        if(!ii) jcol+=24;
        ic++;
        concat(spot_freq, packet_bmap_lines[i], 0, 6, COPY);
        real_to_char (rcv.radio_freq, radio_freq, 1);
        left_blank_pad (radio_freq, sizeof(radio_freq));
        if(!strcmp(radio_freq, spot_freq))
         write_line (row1+ii, jcol-1, ">", YELLOW, SAVEPIX);
        else
         write_line (row1+ii, jcol-1, ">",
          packet_box_color[ipage_screen[0][idisplay_type]], SAVEPIX);
       }
     }
    else
     {
      imin = 0;
      imax = -1;
      draw_rectangle (&update_rect,
       packet_box_color[ipage_screen[0][idisplay_type]], SAVEPIX);
      if(pbm.spot_num>-1)
       {
        fill_kb_dt ();
        for(i=pbm.spot_num; i>=0; i--)
         {
          if(atof(pbm.frequency[i])>packet_band_limits[packet_band][0] &&
             atof(pbm.frequency[i])<packet_band_limits[packet_band][1])
           {
            if(bmap_num>MAX_BMAP_LINES-2)
             break;
            if(idelta_time (pbm.date[i], kb_dt.date,
               pbm.time[i], kb_dt.time)>MAX_SPOT_AGE)
             break;
            if(strlen(pbm.call[i])>2)
             {
              bmap_num++;
              strcpy(packet_bmap_lines[bmap_num], pbm.frequency[i]);
              strcat(packet_bmap_lines[bmap_num], " ");
              strcat(packet_bmap_lines[bmap_num], pbm.call[i]);
             }
           }
         }
        for(i=PBM_LINES-1; i>pbm.spot_num; i--)
         {
          if(atof(pbm.frequency[i])>packet_band_limits[packet_band][0] &&
             atof(pbm.frequency[i])<packet_band_limits[packet_band][1])
           {
            if(bmap_num>MAX_BMAP_LINES-2)
             break;
            if(idelta_time (pbm.date[i], kb_dt.date,
               pbm.time[i], kb_dt.time)>MAX_SPOT_AGE)
             break;
            if(strlen(pbm.call[i])>2)
             {
              bmap_num++;
              strcpy(packet_bmap_lines[bmap_num], pbm.frequency[i]);
              strcat(packet_bmap_lines[bmap_num], " ");
              strcat(packet_bmap_lines[bmap_num], pbm.call[i]);
             }
           }
         }
        bmap_num = sort_bmap_lines (packet_bmap_lines, bmap_num);
        if(bmap_num>-1)
         {
          if(packet_bmap_page>bmap_num/36)
           {
            packet_bmap_page = bmap_num/36;
            play_bells (BELL_SOUND);
           }
          imin = packet_bmap_page*36;
          imax = (packet_bmap_page+1)*36-1;
          if(imax>bmap_num)
           imax = bmap_num;
          for(i=imin; i<=imax; i++)
           {
            ii = ic%12;
            if(!ii) jcol+=24;
            ic++;
            if(packet_search_tree (packet_bmap_lines[i],
                                   packet_rec_county, call_px))
             spot_color = LT_GRAY;
            else
             {
              switch (isel_contest)
               {
                case DX :
                case WW :
                 if(strlen(packet_rec_county))
                  ipci = get_packet_country_index (packet_rec_county);
                 else
                  ipci = get_packet_country (packet_bmap_lines[i], call_px);
                 unknown = !ipci;
                 new_mult = !countries.icountry_worked[mb][ipci];
                 break;
                case WPX :
                 if(strlen(packet_rec_county))
                  ipci = get_packet_country_index (packet_rec_county);
                 else
                  ipci = get_packet_country (packet_bmap_lines[i], call_px);
                 unknown = FALSE;
                 new_mult = packet_search_px_tree (ipci, call_px);
                 break;
                default :
                 unknown = FALSE;
                 new_mult = FALSE;
               }
              if(unknown)
               spot_color = HI_RED;
              else if(new_mult)
               spot_color = YELLOW;
              else
               spot_color = WHITE;
             }
            write_line (row1+ii, jcol, packet_bmap_lines[i],
                        spot_color, SAVEPIX);
           }
         }
       }
     }
   }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-idr*wcol,
                              update_rect.y-idr*hrow,
                              update_rect.width+idr*2*wcol,
                              update_rect.height+idr*2*hrow);
}

static gint sort_bmap_lines(gchar bmap_lines[][22], gint bmap_num)
{
  register gint i, j;
  gint exchange;
  gchar bmap_line_hold[22];

  do
   {
    exchange = 0;
    for(i=bmap_num; i>0; i--)
     if(atof(bmap_lines[i])<atof(bmap_lines[i-1]))
      {
       strcpy(bmap_line_hold, bmap_lines[i-1]);
       strcpy(bmap_lines[i-1], bmap_lines[i]);
       strcpy(bmap_lines[i], bmap_line_hold);
       exchange = 1;
      }
    for(i=1; i<=bmap_num; i++)
     if(atof(bmap_lines[i])<atof(bmap_lines[i-1]))
      {
       strcpy(bmap_line_hold, bmap_lines[i-1]);
       strcpy(bmap_lines[i-1], bmap_lines[i]);
       strcpy(bmap_lines[i], bmap_line_hold);
       exchange = 1;
      }
   } while(exchange);
  for(i=1; i<=bmap_num; i++)
   if(!strcmp(bmap_lines[i], bmap_lines[i-1]))
    {
     for(j=i; j<bmap_num; j++)
      strcpy(bmap_lines[j], bmap_lines[j+1]);
     bmap_num--;
     i--;
    }
  return bmap_num;
}

static void creader_volume_box(GtkWidget *widget, gint idraw)
{
  GdkRectangle update_rect;
  gint volume_color;
  gint row1=4, col1=1, row2=6, col2=28;
  const gchar *subtitle="Low      Mid      High";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  if(idraw)
   draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
             "Volume", WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, MID_GRAY, SAVEPIX);
  switch (creader_vol/5)
   {
    case 2 :
    case 3 :
     volume_color = HI_GREEN;
     break;
    case 1 :
    case 4 :
     volume_color = YELLOW;
     break;
    default :
     volume_color = HI_RED;
   }
  write_line (row1, creader_vol, "^", volume_color, SAVEPIX);
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-idraw*wcol,
                              update_rect.y-idraw*hrow,
                              update_rect.width+idraw*2*wcol,
                              update_rect.height+idraw*2*hrow);
}

static void creader_tuning_box(GtkWidget *widget, gint idraw)
{
  GdkRectangle update_rect;
  gint tuning_color;
  gint row1=4, col1=53, row2=6, col2=80;
  const gchar *subtitle="450      600       750";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  if(idraw)
   draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
             "Tuning", WHITE, subtitle, LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, MID_GRAY, SAVEPIX);
  switch (creader_freq/5)
   {
    case 12 :
    case 13 :
     tuning_color = HI_GREEN;
     break;
    case 11 :
    case 14 :
     tuning_color = YELLOW;
     break;
    default :
     tuning_color = HI_RED;
   }
  write_line (row1, creader_freq, "^", tuning_color, SAVEPIX);
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-idraw*wcol,
                              update_rect.y-idraw*hrow,
                              update_rect.width+idraw*2*wcol,
                              update_rect.height+idraw*2*hrow);
}

static void creader_speed_box(GtkWidget *widget, gint idraw)
{
  GdkRectangle update_rect;
  gint row1=4, col1=30, row2=6, col2=51;
  const gchar *subtitle="20     45     70";

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  if(idraw)
   {
    draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
              "Speed", WHITE, subtitle, LT_GRAY, SAVEPIX);
    black_bar (widget, row1, col1-1, row2, col1-1);
    black_bar (widget, row1, col2+1, row2, col2+1);
   }
  draw_rectangle (&update_rect, ORANGE, SAVEPIX);
  write_line (row1, creader_speed, "^", WHITE, SAVEPIX);
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-idraw*wcol,
                              update_rect.y-idraw*hrow,
                              update_rect.width+idraw*2*wcol,
                              update_rect.height+idraw*2*hrow);
}

static void creader_box(GtkWidget *widget, gint idraw)
{
  GdkRectangle update_rect;
  gint i;
  gint ii=-1;
  gint row1=7, col1=1, row2=17, col2=80;

  update_rect.x = col1*wcol;
  update_rect.y = row1*hrow;
  update_rect.width = (col2-col1-1)*wcol;
  update_rect.height = (row2-row1-1)*hrow;
  if(idraw)
   draw_box (row1, col1, row2, col2, 2, LT_GRAY, BLACK,
             "Code Reader", WHITE, "", LT_GRAY, SAVEPIX);
  draw_rectangle (&update_rect, MID_GRAY, SAVEPIX);
  if(creader_line_num>-1)
   {
    for(i=creader_line_num+1; i<14-log_lines[IDT_CREADER]; i++)
     {
      ii++;
      write_line (row1+ii, 2, creader_array[i], WHITE, SAVEPIX);
     }
    for(i=0; i<=creader_line_num; i++)
     {
      ii++;
      write_line (row1+ii, 2, creader_array[i], WHITE, SAVEPIX);
     }
   }
  gtk_widget_queue_draw_area (widget,
                              update_rect.x-idraw*wcol,
                              update_rect.y-idraw*hrow,
                              update_rect.width+idraw*2*wcol,
                              update_rect.height+idraw*2*hrow);
}

static gint start_creader(void)
{
  struct stat statbuf;
  gchar cline_start[100];
  gint crdsp = FALSE;
  const gchar *soxline =
   "rec --buffer 1024 -q -c 1 -r 8k -t dat - bandpass 600 400 ";
  const gchar *filnoise = "PROFILE.QRN";

  if(stat(fifocr, &statbuf))
   mkfifo(fifocr, 0777);
  else
   {
    remove(fifocr);
    mkfifo(fifocr, 0777);
   }
  fd_fifocr = open(fifocr, O_RDONLY|O_NONBLOCK);
  if(fd_fifocr>-1)
   {
    setenv("AUDIODRIVER", "oss", TRUE);
    strcpy(cline_start, soxline);
    if(!stat(filnoise, &statbuf))
     {
      strcat(cline_start, "noisered ");
      strcat(cline_start, filnoise);
      strcat(cline_start, " 0.2 ");
      crdsp = TRUE;
     }
    strcat(cline_start, "| ./kb_creader &");
    system(cline_start);
    sleep(1);
    isys_creader = get_running_pid ("kb_creader");
    if(isys_creader<0)
     {
      unsetenv("AUDIODRIVER");
      system(cline_start);
      sleep(1);
      isys_creader = get_running_pid ("kb_creader");
      if(isys_creader<0)
       {
        close(fd_fifocr);
        remove(fifocr);
        fd_fifocr = -1;
       }
     }
   }
  return crdsp;
}

static void stop_creader(void)
{
  gint ipid;

  ipid = get_running_pid ("rec");
  if(ipid>-1)
   {
    kill(ipid, SIGTERM);
    unsetenv("AUDIODRIVER");
   }
  if(fd_fifocr>-1)
   {
    close(fd_fifocr);
    remove(fifocr);
    isys_creader = -1;
   }
}

static void fill_creader_array(void)
{
  gint i, iread;
  gchar crl[32];
  static gint cnum=-1;

  while((iread = read(fd_fifocr, crl, sizeof(crl)))>0)
   for(i=0; i<iread; i++)
    {
     if(crl[i]<-80)
      creader_vol = (-(crl[i]+80)*2+1)/3;
     else if(crl[i]<-40)
      creader_freq = 25+(-crl[i]*2+2)/3;
     else if(crl[i]<0)
      creader_speed = 27+(137/(-crl[i]));
     else
      {
       cnum++;
       cnum %= 76;
       if(!cnum)
        {
         creader_line_num++;
         creader_line_num %= 9;
         memset(creader_array[creader_line_num], '\0',
                sizeof(creader_array[creader_line_num]));
        }
       creader_array[creader_line_num][cnum] = crl[i];
      }
    }
}
