/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#ifdef _MANGLE_INC
#include "gui/TEXT_~ZG.HH"
#else
#include "gui/text_scroll.hh"
#endif
#include "window/style.hh"
#include "area/rectlist.hh"
static inline int fmt_char(char c)
{
if ((c>='a' && c<='z') || (c>='A' && c<='Z'))
return 1;
return 0;
}
void i4_text_scroll_window_class::printf(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
while (*fmt)
{
if (*fmt=='%')
{
char *fmt_end=fmt;
while (!fmt_char(*fmt_end) && *fmt_end) fmt_end++;
char f[10], out[500];
memcpy(f, fmt, fmt_end-fmt+1);
f[fmt_end-fmt+1]=0;
out[0]=0;
switch (*fmt_end)
{
case 's' :
{
char *str=va_arg(ap,char *);
output_string(str);
} break;
case 'd' :
case 'i' :
case 'x' :
case 'X' :
case 'c' :
case 'o' :
{
::sprintf(out,f,va_arg(ap,int));
output_string(out);
} break;
case 'f' :
case 'g' :
::sprintf(out,f,va_arg(ap,double));
output_string(out);
break;
default :
::sprintf(out,f,va_arg(ap,void *));
output_string(out);
break;
}
fmt=fmt_end;
if (*fmt)
fmt++;
}
else
{
output_char(*fmt);
fmt++;
}
}
va_end(ap);
}
i4_text_scroll_window_class::i4_text_scroll_window_class(i4_graphical_style_class *style,
i4_color text_foreground,
i4_color text_background,
w16 width, w16 height) // in pixels
: i4_parent_window_class(width, height),
style(style),
fore(text_foreground),
back(text_background)
{
i4_font_class *fnt=style->font_hint->normal_font;
term_height=height/fnt->largest_height();
term_size=(width/fnt->largest_width() + 1) * term_height;
if (!term_size)
term_size=512;
term_out=(i4_char *)i4_malloc(term_size, "terminal chars");
draw_start=term_out;
line_height=fnt->largest_height()+1;
*term_out=0;
dx=dy=tdx=tdy=0;
need_clear=i4_T;
used_size = 0;
}
void i4_text_scroll_window_class::skip_first_line()
{
i4_font_class *fnt=style->font_hint->normal_font;
w32 x=0, wd=width(), count=0;
i4_char *s=term_out;
while (s->value() && xvalue()=='\n')
x=wd;
else
x+=fnt->width(*s);
count++;
s++;
}
memmove(term_out, s, used_size-count+1);
used_size-=count;
}
void i4_text_scroll_window_class::output_string(char *string)
{
while (*string)
{
output_char( (i4_char)(*string));
string++;
}
}
void i4_text_scroll_window_class::output_char(const i4_char &ch)
{
sw32 i;
i4_font_class *fnt=style->font_hint->normal_font;
if (used_size+2>term_size)
{
term_size+=100;
i4_char *old_spot=term_out;
term_out=(i4_char *)i4_realloc(term_out, term_size, "terminal chars");
dx=dy=0;
draw_start=term_out;
need_clear=i4_T;
}
if (!redraw_flag)
request_redraw();
tdx+=fnt->width(ch);
if (tdx>=width() || ch=='\n')
{
tdx=0;
tdy+=line_height;
if (tdy+line_height>height())
{
skip_first_line();
tdy-=line_height;
dx=dy=0;
draw_start=term_out;
need_clear=i4_T;
}
}
term_out[used_size++]=ch;
term_out[used_size]=0;
}
void i4_text_scroll_window_class::clear()
{
draw_start=term_out;
*term_out=0;
dx=dy=tdx=tdy=0;
need_clear=i4_T;
used_size = 0;
request_redraw(i4_F);
}
void i4_text_scroll_window_class::resize(w16 new_width, w16 new_height)
{
i4_font_class *fnt=style->font_hint->normal_font;
term_height=new_height/fnt->largest_height();
int new_size=(new_width/fnt->largest_width() + 1) * term_height;
if (new_size>term_size)
{
term_size=new_size;
if (!term_size)
term_size=512;
if (term_out)
term_out=(i4_char *)i4_realloc(term_out, term_size, "terminal chars");
else
{
term_out=(i4_char *)i4_malloc(term_size, "terminal chars");
term_out[0]=0;
}
}
dx=dy=tdx=tdy=0;
used_size = 0;
i4_parent_window_class::resize(new_width, new_height);
}
void i4_text_scroll_window_class::parent_draw(i4_draw_context_class &context)
{
i4_font_class *fnt=style->font_hint->normal_font;
if (!undrawn_area.empty())
{
draw_start=term_out;
dx=dy=0;
need_clear=i4_T;
}
if (need_clear)
{
if (back==style->color_hint->neutral())
style->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);
else
local_image->clear(back, context);
need_clear=i4_F;
}
fnt->set_color(fore);
while (draw_start->value())
{
if (draw_start->value()=='\n')
dx=width()+1;
else
{
fnt->put_character(local_image, dx,dy, *draw_start, context);
dx+=fnt->width(*draw_start);
}
if (dx>=width())
{
dx=0;
dy+=fnt->largest_height();
}
draw_start++;
}
tdx=dx;
tdy=dy;
i4_parent_window_class::parent_draw(context);
}
i4_bool i4_text_scroll_window_class::need_redraw()
{
if (draw_start->value())
return i4_T;
else
return i4_parent_window_class::need_redraw();
}