/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */
/* routines for left-justified, right-justified and centered text */
/* wrapping text courtesy of Hal Birkeland [hkbirke@media-lab.mit.edu] */
#include<stdio.h>
#include"xpointer.h"
#include "display.h"

unsigned int get_window_width(win_id)
     int win_id;
{
  extern XContext width_context;
  extern Display *dpy;
  XContext context;
  int width_ret, x, y_ret;
  unsigned int width, height, border, depth, *width_point;
  Window root_return;
  
  if (!XFindContext(dpy, win_id, width_context, (caddr_t *)&width_point)) 
    return(*width_point);

  XGetGeometry(dpy, win_id, &root_return, &x, &y_ret, &width,
	       &height, &border, &depth);
  width_point = (unsigned int *)malloc(1 * sizeof(unsigned int));
  /*If the malloc fails, no big deal, we'll just look it up next time, too.*/
  if (width_point) {
    *width_point = width;
    XSaveContext(dpy, win_id, width_context, width_point);
  }
  return(width);
}

int TextWidth (font, chars, len)
     XFontStruct *font;
     char *chars;
     int len;

{
  register int width = 0, ch; 
  int i;

  for (i = 0; i < len; i++) {
    ch = chars[i] - font->min_char_or_byte2;
    if (ch < 0 || ch > font->max_char_or_byte2) continue;
    if (font->per_char == NULL) width += font->min_bounds.width;
    else width += font->per_char[ch].width;
  }
  return (width);
}

simple_text( dpy, window, gc, fs, x, y, string)
     Display *dpy;
     Window window;
     GC gc;
     XFontStruct *fs;
     int x, y;
     char *string;
{
  int length;

  length = strlen(string);
  XDrawString( dpy, window, gc, x, y, string, length);

}

left_text(dpy, window, gc, fs, y, string)
     Display *dpy;
     Window window;
     GC gc;
     XFontStruct *fs;
     int y;
     char *string;
{
  int length;
  
  length = strlen(string);
  XDrawString( dpy, window, gc, 4, y, string, length);
}

right_text(dpy, window, gc, fs, y, string)
     Display *dpy;
     Window window;
     GC gc;
     XFontStruct *fs;
     int y;
     char *string;
{
  int length, swidth;
  int x, y_ret;
  unsigned int width, height, border, depth;
  Window root;
  length = strlen(string);
  swidth = TextWidth( fs, string, length);
  width = get_window_width(window);

  XDrawString( dpy, window, gc, width-swidth-4, y, string, length);
}

center_text(dpy, window, gc, fs, y, string)
     Display *dpy;
     Window window;
     GC gc;
     XFontStruct *fs;
     int y;
     char *string;
{
  int length, left;
  int swidth;
  Window root_return;
  int x, y_ret;
  unsigned int width, height, border, depth;

  length = strlen(string);
  swidth = TextWidth( fs, string, length);
  width = get_window_width(window);
  left = width/2 - swidth/2;

  XDrawString( dpy, window, gc, left, y, string, length);
}

int count_text_lines (dpy, win, text, font, rect, chars)
     Display *dpy;
     Window win;
     GC text;
     XFontStruct *font;
     XRectangle *rect;
     char *chars;

{
  int  width, numchars, num2chars, eol, lines = 0;
  char *current_line, *line;

  current_line = chars;
  
  while (*current_line != '\0') {
    
    /* can text till next EOL fit on one line */
    numchars = (int) ((long) strchr(current_line, '\n') - (long) current_line);
    if ((numchars >= 0) &&
	(TextWidth (font, current_line, numchars) < rect->width)) {
      line = current_line + numchars + 1;
    } else {
      /* count till word break passes width of line */
      width = 0;
      num2chars = 0;
      line = current_line;
      eol = 0;
      while ((width < (int) rect->width) && !eol) {
	numchars = num2chars;
	if ((line = (char *) strchr (line, ' ')) < current_line) {
	  num2chars = strlen(current_line);
	  eol = 1;
	} else {
	  num2chars = (int) ((long)line - (long)current_line);
	}
	width = TextWidth (font, current_line, num2chars);
	line +=1;
      }
    }
    
    /* handle case when first word does not fit on the line 
    if (line == current_line) 
      /* right now, just fit what you can 
      numchars = (int) ((long) strchr(line,' ') - (long)current_line);
    */
    /* find actual width of current line */
    width = TextWidth (font, current_line, numchars);
    lines++;
    current_line += numchars + 1;
  }
  return (lines);
}

char *
justify_text (dpy, win, text, font, rect, chars, mode, leading)
     Display *dpy;
     Window win;
     GC text;
     XFontStruct *font;
     XRectangle *rect;
     char *chars;
     int mode, leading;

{
  int  width, numchars, num2chars, yc, eol, lead_part = 0; 
  char *current_line, *line;
  
  yc = rect->y + font->ascent + 1;
  current_line = chars;
  
  while ((*current_line != '\0') && (yc < (rect->y + rect->height + font->ascent))) {
    
    /* can text till next EOL fit on one line */
    numchars = (int) ((long) strchr(current_line, '\n') - (long) current_line);
    if ((numchars >= 0) &&
	(TextWidth (font, current_line, numchars) < rect->width)) {
      line = current_line + numchars + 1;
    } else {
      /* count till word break passes width of line */
      width = 0;
      num2chars = 0;
      line = current_line;
      eol = 0;
      while ((width < (int) rect->width) && !eol) {
	numchars = num2chars;
	if ((line = (char *) strchr (line, ' ')) < current_line) {
	  num2chars = strlen(current_line);
	  eol = 1;
	} else {
	  num2chars = (int) ((long)line - (long)current_line);
	}
	width = TextWidth (font, current_line, num2chars);
	line +=1;
      }
    }
    
    /* handle case when first word does not fit on the line 
    if (line == current_line) 
      /* right now, just fit what you can 
      numchars = (int) ((long) strchr(line,' ') - (long)current_line);
    */
    /* find actual width of current line */
    width = TextWidth (font, current_line, numchars);

    switch (mode) {
      case CENTER_JUSTIFIED: {
	XDrawString (dpy, win, text, (rect->x + ((rect->width - width)/2)), yc, 
		     current_line, numchars);
	break;
      }
      case RIGHT_JUSTIFIED: {
	XDrawString (dpy, win, text, (rect->x + rect->width - width), yc,
		     current_line, numchars);
	break;
      }
      default: /* TOP_LEFT_JUSTIFIED */
	XDrawString (dpy, win, text, rect->x, yc, current_line, numchars);
      }
    lead_part += (leading%100);
    yc += font->ascent + font->descent + (leading / 100) + (lead_part / 100);
    current_line += numchars + 1;
  }
  return (current_line);
}



char *
display_text (dpy, win, text, font, rect, chars, mode, leading)
     Display *dpy;
     Window win;
     GC text;
     XFontStruct *font;
     XRectangle *rect;
     char *chars;
     int mode, leading;

{
  XRectangle new_rect;
  int text_height, new_leading, line_count,
  spread_mode = (mode & SPREAD_TEXT);
  
  new_rect.x = rect->x;
  new_rect.y = rect->y;
  new_rect.height = rect->height;
  new_rect.width = rect->width;

  line_count = count_text_lines (dpy, win, text, font, rect, chars);
  text_height = ((font->ascent + font->descent) * 100 + leading) * line_count;

  switch (spread_mode) {
  case CENTER_TEXT: {
    new_leading = leading;
    if (text_height <= rect->height) {
      new_rect.height = text_height;
      new_rect.y = rect->y + rect->height/2 - text_height/2;
    }
  }
  case SPREAD_TEXT: {
    if (text_height < rect->height)
      new_leading = leading +
	(((((rect->height - text_height)*100)<<8) / line_count)>>8);
    else new_leading = leading;
  }
  case SQUEEZE_TEXT: {
    if (text_height > rect->height)
      new_leading = leading +
	(((((rect->height - text_height)*100)<<8) / line_count)>>8);
    else new_leading = leading;
  }
  case SPREAD_SQUEEZE_TEXT: {
    new_leading = leading +
      (((((rect->height - text_height)*100)<<8) / line_count)>>8);
  }
  case BOTTOM_TEXT: {
    new_leading = leading;
    if (text_height <= rect->height) {
      new_rect.height = text_height;
      new_rect.y = rect->y + rect->height - text_height;
    }
  }
  default:{
    new_leading = leading;
  }
  }

  return (justify_text (dpy, win, text, font, &new_rect, chars,
			(mode & JUSTIFY_MASK),	new_leading));
}





