text: /*s: windows/libframe/frselect.c */
  #include <u.h>
  #include <libc.h>
  #include <draw.h>
  #include <thread.h>
  #include <mouse.h>
  #include <frame.h>
  
  /*s: function [[region]] */
  static
  int
  region(int a, int b)
  {
      if(a < b)
          return -1;
      if(a == b)
          return 0;
      return 1;
  }
  /*e: function [[region]] */
  
  /*s: function [[frselect]] */
  void
  frselect(Frame *f, Mousectl *mc)	/* when called, button 1 is down */
  {
      ulong p0, p1, q;
      Point mp, pt0, pt1, qt;
      int reg, b, scrled;
  
      mp = mc->xy;
      b = mc->buttons;
  
      f->modified = 0;
      frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 0);
      p0 = p1 = frcharofpt(f, mp);
      f->p0 = p0;
      f->p1 = p1;
      pt0 = frptofchar(f, p0);
      pt1 = frptofchar(f, p1);
      frdrawsel(f, pt0, p0, p1, 1);
      reg = 0;
      do{
          scrled = 0;
          if(f->scroll){
              if(mp.y < f->r.min.y){
                  (*f->scroll)(f, -(f->r.min.y-mp.y)/(int)f->font->height-1);
                  p0 = f->p1;
                  p1 = f->p0;
                  scrled = 1;
              }else if(mp.y > f->r.max.y){
                  (*f->scroll)(f, (mp.y-f->r.max.y)/(int)f->font->height+1);
                  p0 = f->p0;
                  p1 = f->p1;
                  scrled = 1;
              }
              if(scrled){
                  if(reg != region(p1, p0))
                      q = p0, p0 = p1, p1 = q;	/* undo the swap that will happen below */
                  pt0 = frptofchar(f, p0);
                  pt1 = frptofchar(f, p1);
                  reg = region(p1, p0);
              }
          }
          q = frcharofpt(f, mp);
          if(p1 != q){
              if(reg != region(q, p0)){	/* crossed starting point; reset */
                  if(reg > 0)
                      frdrawsel(f, pt0, p0, p1, 0);
                  else if(reg < 0)
                      frdrawsel(f, pt1, p1, p0, 0);
                  p1 = p0;
                  pt1 = pt0;
                  reg = region(q, p0);
                  if(reg == 0)
                      frdrawsel(f, pt0, p0, p1, 1);
              }
              qt = frptofchar(f, q);
              if(reg > 0){
                  if(q > p1)
                      frdrawsel(f, pt1, p1, q, 1);
                  else if(q < p1)
                      frdrawsel(f, qt, q, p1, 0);
              }else if(reg < 0){
                  if(q > p1)
                      frdrawsel(f, pt1, p1, q, 0);
                  else
                      frdrawsel(f, qt, q, p1, 1);
              }
              p1 = q;
              pt1 = qt;
          }
          f->modified = 0;
          if(p0 < p1) {
              f->p0 = p0;
              f->p1 = p1;
          }
          else {
              f->p0 = p1;
              f->p1 = p0;
          }
          if(scrled)
              (*f->scroll)(f, 0);
          flushimage(f->display, 1);
          if(!scrled)
              readmouse(mc);
          mp = mc->xy;
      }while(mc->buttons == b);
  }
  /*e: function [[frselect]] */
  
  /*s: function [[frselectpaint]] */
  void
  frselectpaint(Frame *f, Point p0, Point p1, Image *col)
  {
      int n;
      Point q0, q1;
  
      q0 = p0;
      q1 = p1;
      q0.y += f->font->height;
      q1.y += f->font->height;
      n = (p1.y-p0.y)/f->font->height;
      if(f->b == nil)
          drawerror(f->display, "frselectpaint b==0");
      if(p0.y == f->r.max.y)
          return;
      if(n == 0)
          draw(f->b, Rpt(p0, q1), col, nil, ZP);
      else{
          if(p0.x >= f->r.max.x)
              p0.x = f->r.max.x-1;
          draw(f->b, Rect(p0.x, p0.y, f->r.max.x, q0.y), col, nil, ZP);
          if(n > 1)
              draw(f->b, Rect(f->r.min.x, q0.y, f->r.max.x, p1.y),
                  col, nil, ZP);
          draw(f->b, Rect(f->r.min.x, p1.y, q1.x, q1.y),
              col, nil, ZP);
      }
  }
  /*e: function [[frselectpaint]] */
  /*e: windows/libframe/frselect.c */
  