/programs/develop/libraries/libGUI/SRC/compilation/MinGW/build.bat |
---|
0,0 → 1,3 |
gcc -c -O2 -nostdinc -nostdlib -march=pentium -fomit-frame-pointer -fno-builtin -o libGUI.obj libGUI.c |
strip -X --strip-unneeded libGUI.obj |
@pause |
/programs/develop/libraries/libGUI/SRC/compilation/MinGW |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/libGUI/SRC/compilation/cygwin/Makefile |
---|
0,0 → 1,11 |
SRC = libGUI.c |
TARGET = libGUI.obj |
CFLAGS = -O2 -nostdinc -nostdlib -march=pentium -fomit-frame-pointer -fno-builtin -fno-builtin-printf |
CC = gcc |
all: |
$(CC) -c $(SRC) $(CFLAGS) -o $(TARGET) |
strip -x -S $(TARGET) |
$(CC) -S $(SRC) $(CFLAGS) |
clean: |
rm $(TARGET) |
/programs/develop/libraries/libGUI/SRC/compilation/cygwin |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/libGUI/SRC/compilation |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/libGUI/SRC/control_button.h |
---|
0,0 → 1,11 |
/* |
control button data |
*/ |
#define FLAG_INSERT_BUTTON_ON 0x1; |
#define FLAG_INSERT_BUTTON_OFF 0xfe; |
#define FLAG_PRESSED_BUTTON_ON 0x2 |
#define FLAG_PRESSED_BUTTON_OFF 0xfd |
#define FLAG_RELEASED_BUTTON_ON 0x4 |
#define FLAG_RELEASED_BUTTON_OFF 0xfb |
/programs/develop/libraries/libGUI/SRC/control_button.inc |
---|
0,0 → 1,414 |
/* |
control Button |
*/ |
void DrawFocuseForButton(struct ControlButton *Button) |
{ |
int x; |
int y; |
int sizex; |
int sizey; |
struct FINITION *fin; |
x=Button->ctrl_x; |
y=Button->ctrl_y; |
sizex=Button->ctrl_sizex; |
sizey=Button->ctrl_sizey; |
fin=(struct FINITION*)Button->finition; |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizey,0xbfff); |
} |
void DrawPressedButton(struct ControlButton *Button) |
{ |
int x; |
int y; |
int sizex; |
int sizey; |
struct FINITION *fin; |
gui_message_t message; |
x=Button->ctrl_x; |
y=Button->ctrl_y; |
sizex=Button->ctrl_sizex; |
sizey=Button->ctrl_sizey; |
fin=(struct FINITION*)Button->finition; |
Draw(fin,TOOL_GRADIENT_DOWN_FILLED_RECTANGLE,x,y,sizex,sizey/2,COLOR_FON,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_GRADIENT_DOWN_FILLED_RECTANGLE,x,y+sizey/2,sizex,sizey/2,COLOR_MIDDLE_LIGHT,COLOR_FON); |
Draw(fin,TOOL_HORIZONTAL_LINE,x,x+sizex-1,y,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_VERTICAL_LINE,x,y,y+sizey-1,COLOR_LIGHT); |
Draw(fin,TOOL_HORIZONTAL_LINE,x,x+sizex-1,y+sizey-1,COLOR_LIGHT); |
Draw(fin,TOOL_VERTICAL_LINE,x,y,y+sizey-1,COLOR_ABSOLUTE_DARK); |
if (fin->flags & FINITION_ON) |
{ |
message.type=MESSAGE_FULL_REDRAW_ALL_WITH_FINITION; |
message.arg1=fin->x; |
message.arg2=fin->y; |
message.arg3=fin->sizex; |
message.arg4=fin->sizey; |
} |
else |
{ |
message.type=MESSAGE_FULL_REDRAW_ALL; |
} |
SendMessage((struct HEADER*)Button,&message); |
if (Button->flags & FLAG_FOCUSE_INPUT_ON) DrawFocuseForButton(Button); |
} |
void DrawInsertButton(struct ControlButton *Button) |
{ |
int x; |
int y; |
int sizex; |
int sizey; |
struct FINITION *fin; |
x=Button->ctrl_x; |
y=Button->ctrl_y; |
sizex=Button->ctrl_sizex; |
sizey=Button->ctrl_sizey; |
fin=(struct FINITION*)Button->finition; |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizey,COLOR_INSERT); |
} |
void DrawButton(struct ControlButton *Button) |
{ |
int x; |
int y; |
int sizex; |
int sizey; |
struct FINITION *fin; |
gui_message_t message; |
x=Button->ctrl_x; |
y=Button->ctrl_y; |
sizex=Button->ctrl_sizex; |
sizey=Button->ctrl_sizey; |
fin=(struct FINITION*)Button->finition; |
Draw(fin,TOOL_GRADIENT_UP_FILLED_RECTANGLE,x,y,sizex,sizey,COLOR_FON,COLOR_MIDDLE_LIGHT); |
//Draw(fin,TOOL_GRADIENT_DOWN_FILLED_RECTANGLE,x,y+sizey/2,sizex,sizey/2,COLOR_FON,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizey,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_HORIZONTAL_LINE,x+1,x+sizex-2,y+1,COLOR_LIGHT); |
Draw(fin,TOOL_VERTICAL_LINE,x+sizex-2,y+1,y+sizey-2,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_HORIZONTAL_LINE,x+1,x+sizex-2,y+sizey-2,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_VERTICAL_LINE,x+1,y+1,y+sizey-2,COLOR_LIGHT); |
if (Button->child_bk!=NULL) |
{ |
if (fin->flags & FINITION_ON) |
{ |
message.type=MESSAGE_FULL_REDRAW_ALL_WITH_FINITION; |
message.arg1=fin->x; |
message.arg2=fin->y; |
message.arg3=fin->sizex; |
message.arg4=fin->sizey; |
} |
else |
{ |
message.type=MESSAGE_FULL_REDRAW_ALL; |
} |
SendMessage((struct HEADER*)Button,&message); |
} |
if (Button->flags & FLAG_FOCUSE_INPUT_ON) DrawFocuseForButton(Button); |
} |
//--------------------------------------------------------------------------------- |
// control Button |
//--------------------------------------------------------------------------------- |
void ButtonProc(struct ControlButton *button,struct MESSAGE *message) |
{ |
int x,y,btn_state; |
char v; |
struct TIMER *timer; |
struct FINITION *fin; |
parent_t *main_parent; |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//draw button |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
fin=(struct FINITION*)button->finition; |
fin->flags=fin->flags | FINITION_ON; |
fin->x=message->arg1; |
fin->y=message->arg2; |
fin->sizex=message->arg3; |
fin->sizey=message->arg4; |
DrawButton(button); |
break; |
} |
case MESSAGE_KEYS_EVENT: |
{ |
main_parent=(parent_t*)button->main_parent; |
//not relazed yet |
if (button->flags & FLAG_FOCUSE_INPUT_ON) |
{ |
if (message->arg1==KEY_DOWN) |
{ |
if (message->arg2==SC_SPACE) |
{ |
button->btn_flags=button->btn_flags | FLAG_PRESSED_BUTTON_ON; |
if (ControlCheckCallbackEvent(button,(DWORD)BUTTON_PRESSED_EVENT)!=NULL) |
{ |
button->flags=button->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)button; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(button,(DWORD)BUTTON_PRESSED_EVENT); |
main_parent->number_callbacks++; |
} |
if (button->flags & FLAG_SHOW_CONTROL) DrawPressedButton(button); |
} |
} |
else |
{ |
if (message->arg2==SC_SPACE) |
{ |
button->btn_flags=button->btn_flags | FLAG_RELEASED_BUTTON_ON; |
button->btn_flags=button->btn_flags & FLAG_PRESSED_BUTTON_OFF; |
if (ControlCheckCallbackEvent(button,(DWORD)BUTTON_RELEASED_EVENT)!=NULL) |
{ |
button->flags=button->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)button; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(button,(DWORD)BUTTON_RELEASED_EVENT); |
main_parent->number_callbacks++; |
} |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
} |
} |
} |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ |
if (button->flags & FLAG_GET_SPECIALIZED_MESSAGE_ON) |
{ |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
button->flags=button->flags & FLAG_GET_SPECIALIZED_MESSAGE_OFF; |
} |
break; |
} |
case MESSAGE_MOUSE_EVENT: |
{ //check press of mouse buttons |
x=message->arg1; |
y=message->arg2; |
main_parent=(parent_t*)button->main_parent; |
if (message->arg3==MOUSE_LEFT_BUTTON_UP) |
{ |
//insert of button |
if (CheckCrossBox((struct HEADER*)button,x,y)==TRUE) |
{ |
v=button->btn_flags & FLAG_INSERT_BUTTON_ON; |
if ((ControlCheckCallbackEvent(button,(DWORD)BUTTON_ENTER_EVENT)!=NULL) && (v==FALSE)) |
{ |
button->flags=button->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)button; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(button,(DWORD)BUTTON_ENTER_EVENT); |
main_parent->number_callbacks++; |
} |
button->btn_flags=button->btn_flags | FLAG_INSERT_BUTTON_ON; |
if (button->flags & FLAG_SHOW_CONTROL) DrawInsertButton(button); |
} |
else |
{ |
v=button->btn_flags & FLAG_INSERT_BUTTON_ON; |
if (v==TRUE) |
{ |
if (ControlCheckCallbackEvent(button,(DWORD)BUTTON_LEAVE_EVENT)!=NULL) |
{ |
button->flags=button->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)button; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(button,(DWORD)BUTTON_LEAVE_EVENT); |
main_parent->number_callbacks++; |
} |
button->btn_flags=button->btn_flags & FLAG_INSERT_BUTTON_OFF; |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
} |
} |
if (button->btn_flags & FLAG_PRESSED_BUTTON_ON) |
{ |
button->btn_flags=button->btn_flags & FLAG_PRESSED_BUTTON_OFF; |
button->btn_flags=button->btn_flags | FLAG_RELEASED_BUTTON_ON; |
if (ControlCheckCallbackEvent(button,(DWORD)BUTTON_RELEASED_EVENT)!=NULL) |
{ |
button->flags=button->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)button; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(button,(DWORD)BUTTON_RELEASED_EVENT); |
main_parent->number_callbacks++; |
} |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
} |
} |
else |
{ |
if (CheckCrossBox((struct HEADER*)button,x,y)==TRUE) |
{ |
if (message->arg3==MOUSE_LEFT_BUTTON_DOWN) |
{ |
if ((button->btn_flags & FLAG_PRESSED_BUTTON_ON)==FALSE) |
{if (button->flags & FLAG_SHOW_CONTROL) |
DrawPressedButton(button);} |
button->btn_flags=button->btn_flags | FLAG_PRESSED_BUTTON_ON; |
} |
} |
if ((message->arg3==MOUSE_LEFT_BUTTON_DOWN) && (button->btn_flags & FLAG_PRESSED_BUTTON_ON)) |
{ |
if (ControlCheckCallbackEvent(button,(DWORD)BUTTON_PRESSED_EVENT)!=NULL) |
{ |
button->flags=button->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)button; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(button,(DWORD)BUTTON_PRESSED_EVENT); |
main_parent->number_callbacks++; |
} |
} |
} |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
button->ctrl_x=button->ctrl_x+message->arg1; |
button->ctrl_y=button->ctrl_y+message->arg2; |
break; |
} |
case MESSAGE_CALL_TIMER_EVENT: |
{ |
if (button->timer!=(DWORD*)NULL) |
{ |
timer=(struct TIMER*)button->timer; |
if (timer->flags & FLAG_TIMER_ON) Timer(timer); |
} |
break; |
} |
case MESSAGE_SET_FOCUSE: |
{ |
button->flags=button->flags | FLAG_FOCUSE_INPUT_ON; |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
break; |
} |
case MESSAGE_CHANGE_FOCUSE: |
{ |
button->flags=button->flags & FLAG_FOCUSE_INPUT_OFF; |
if (button->flags & FLAG_SHOW_CONTROL) DrawButton(button); |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
if (button->timer!=(DWORD*)NULL) free(button->timer); |
free(button->finition); |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
SendMessage((struct HEADER*)button,message); |
button->main_parent=(DWORD*)message->arg1; |
break; |
} |
default: break; |
} |
//send message to child controls(if there is) |
SendMessage((struct HEADER*)button,message); |
} |
//--------------------------------------------------------------------------------- |
// create control Button |
//--------------------------------------------------------------------------------- |
void* CreateButton(struct ButtonData *info_for_control) |
{ |
struct ControlButton *Button; |
struct FINITION *fin; |
Button=malloc(sizeof(struct ControlButton)); |
Button->finition=malloc(sizeof(struct FINITION)); |
fin=(struct FINITION*)Button->finition; |
fin->flags=0; |
ID++; |
#ifdef DEBUG |
printf("\ncreated button with ID=%d",(int)ID); |
#endif |
Button->child_bk=(DWORD*)NULL; |
Button->child_fd=(DWORD*)NULL; |
Button->active_control_for_keys=(DWORD*)NULL; |
Button->active_control_for_mouse=(DWORD*)NULL; |
Button->callback=(DWORD*)NULL; |
Button->timer=(DWORD*)NULL; |
Button->ctrl_proc=(DWORD*)&ButtonProc; |
Button->ctrl_x=info_for_control->x; |
Button->ctrl_y=info_for_control->y; |
Button->ctrl_sizex=info_for_control->width; |
Button->ctrl_sizey=info_for_control->height; |
Button->ctrl_ID=ID; |
Button->flags=0; |
Button->flags=Button->flags | FLAG_SHOW_CONTROL; |
Button->flags=Button->flags | FLAG_FOCUSE_INPUT_SUPPOROTE; |
Button->btn_flags=0; |
return(Button); |
} |
void* CreateButtonWithText(gui_button_data_t *info,char *txt) |
{ |
gui_button_t *Button; |
gui_text_t *text; |
gui_text_data_t txtdata; |
int len; |
Button=CreateButton(info); |
len=strlen(txt)+1;//one byte for simbol end of string |
txtdata.x=0; |
txtdata.y=0; |
txtdata.font=NULL; |
txtdata.background=FALSE; |
txtdata.color=0; |
txtdata.text=malloc(len); |
memmove(txtdata.text,txt,len); |
txtdata.text[len]='\0'; |
text=CreateText(&txtdata); |
if (text->ctrl_sizex>Button->ctrl_sizex) Button->ctrl_sizex=text->ctrl_sizex+10; |
if (text->ctrl_sizey>Button->ctrl_sizey) Button->ctrl_sizey=text->ctrl_sizey+6; |
text->ctrl_x=(Button->ctrl_sizex/2)-(text->ctrl_sizex/2); |
text->ctrl_y=(Button->ctrl_sizey/2)-(text->ctrl_sizey/2); |
PackControls(Button,text); |
return(Button); |
} |
/programs/develop/libraries/libGUI/SRC/control_image.h |
---|
--- SRC/control_image.inc (nonexistent) |
+++ SRC/control_image.inc (revision 1176) |
@@ -0,0 +1,162 @@ |
+/* |
+ control Image |
+*/ |
+ |
+void DisplayImage(gui_image_t *Image) |
+{ |
+ int x; |
+ int y; |
+ int sizex; |
+ int sizey; |
+ struct FINITION *fin; |
+ |
+ x=Image->ctrl_x; |
+ y=Image->ctrl_y; |
+ sizex=Image->ctrl_sizex; |
+ sizey=Image->ctrl_sizey; |
+ fin=(struct FINITION*)Image->finition; |
+ |
+ Draw(fin,TOOL_IMAGE,x,y,sizex,sizey,Image->bits_per_pixel,Image->img); |
+} |
+ |
+//--------------------------------------------------------------------------------- |
+// control Image |
+//--------------------------------------------------------------------------------- |
+void ImageProc(gui_image_t *Image,gui_message_t *message) |
+{ |
+ finition_t *fin; |
+ |
+ switch(message->type) |
+ { |
+ case MESSAGE_FULL_REDRAW_ALL: |
+ { |
+ //draw Image |
+ if (Image->flags & FLAG_SHOW_CONTROL) DisplayImage(Image); |
+ break; |
+ } |
+ case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
+ { |
+ fin=(struct FINITION*)Image->finition; |
+ fin->flags=fin->flags | FINITION_ON; |
+ fin->x=message->arg1; |
+ fin->y=message->arg2; |
+ fin->sizex=message->arg3; |
+ fin->sizey=message->arg4; |
+ DisplayImage(Image); |
+ break; |
+ } |
+ case MESSAGE_SPECIALIZED: |
+ { |
+ if (Image->flags & FLAG_GET_SPECIALIZED_MESSAGE_ON) |
+ { |
+ if (Image->flags & FLAG_SHOW_CONTROL) DisplayImage(Image); |
+ Image->flags=Image->flags & FLAG_GET_SPECIALIZED_MESSAGE_OFF; |
+ } |
+ break; |
+ } |
+ case MESSAGE_CHANGE_POSITION_EVENT: |
+ { |
+ Image->ctrl_x=Image->ctrl_x+message->arg1; |
+ Image->ctrl_y=Image->ctrl_y+message->arg2; |
+ break; |
+ } |
+ case MESSAGE_DESTROY_CONTROL: |
+ { |
+ free(Image->finition); |
+ free(Image->img); |
+ break; |
+ } |
+ case MESSAGE_SET_MAIN_PARENT: |
+ { |
+ SendMessage((struct HEADER*)Image,message); |
+ Image->main_parent=(DWORD*)message->arg1; |
+ break; |
+ } |
+ |
+ default: break; |
+ } |
+ //send message to child controls(if there is) |
+ SendMessage((struct HEADER*)Image,message); |
+} |
+ |
+//--------------------------------------------------------------------------------- |
+// create control Image |
+//--------------------------------------------------------------------------------- |
+void* CreateImage(struct ImageData *info_for_control) |
+{ |
+ gui_image_t *Image; |
+ finition_t *fin; |
+ DWORD sizemem; |
+ |
+ Image=malloc(sizeof(struct ControlImage)); |
+ Image->finition=malloc(sizeof(struct FINITION)); |
+ fin=(struct FINITION*)Image->finition; |
+ fin->flags=0; |
+ |
+ ID++; |
+#ifdef DEBUG |
+ printf("\ncreated image with ID=%d",(int)ID); |
+#endif |
+ Image->child_bk=(DWORD*)NULL; |
+ Image->child_fd=(DWORD*)NULL; |
+ Image->active_control_for_keys=(DWORD*)NULL; |
+ Image->active_control_for_mouse=(DWORD*)NULL; |
+ Image->callback=(DWORD*)NULL; |
+ Image->timer=(DWORD*)NULL; |
+ |
+ Image->ctrl_proc=(DWORD*)&ImageProc; |
+ Image->ctrl_x=(DWORD)info_for_control->x; |
+ Image->ctrl_y=(DWORD)info_for_control->y; |
+ Image->ctrl_sizex=(DWORD)info_for_control->width; |
+ Image->ctrl_sizey=(DWORD)info_for_control->height; |
+ Image->bits_per_pixel=info_for_control->bits_per_pixel; |
+ Image->ctrl_ID=ID; |
+ Image->flags=0; |
+ Image->flags=Image->flags | FLAG_SHOW_CONTROL; |
+ |
+ switch(Image->bits_per_pixel) |
+ { |
+ case 32: |
+ { |
+ sizemem=(Image->ctrl_sizex*Image->ctrl_sizey)*4; |
+ Image->bytes_per_pixel=4; |
+ break; |
+ } |
+ case 24: |
+ { |
+ sizemem=(Image->ctrl_sizex*Image->ctrl_sizey)*3; |
+ Image->bytes_per_pixel=3; |
+ break; |
+ } |
+ case 16: |
+ { |
+ sizemem=(Image->ctrl_sizex*Image->ctrl_sizey)*2; |
+ Image->bytes_per_pixel=2; |
+ break; |
+ } |
+ case 15: |
+ { |
+ sizemem=(Image->ctrl_sizex*Image->ctrl_sizey)*2; |
+ Image->bytes_per_pixel=2; |
+ break; |
+ } |
+ case 8: |
+ { |
+ sizemem=Image->ctrl_sizex*Image->ctrl_sizey; |
+ Image->bytes_per_pixel=1; |
+ break; |
+ } |
+ case 4: |
+ { |
+ sizemem=((Image->ctrl_sizex*Image->ctrl_sizey)>>1)+1; |
+ Image->bytes_per_pixel=0; |
+ break; |
+ } |
+ default: return(NULL); |
+ } |
+ |
+ Image->img=malloc(sizemem); |
+ |
+ return(Image); |
+} |
+ |
/programs/develop/libraries/libGUI/SRC/control_progress_bar.h |
---|
0,0 → 1,16 |
#define FLAG_PB_VERTICAL_ORIENTATION_ON 0x1 |
#define FLAG_PB_HORIZONTAL_ORIENTATION_ON 0x2 |
#define FLAG_PB_FROM_LEFT_TO_RIGHT_ON 0x4 |
#define FLAG_PB_FROM_RIGHT_TO_LEFT_ON 0x8 |
#define FLAG_PB_FROM_DOWN_TO_UP_ON 0x10 |
#define FLAG_PB_FROM_UP_TO_DOWN_ON 0x20 |
#define FLAG_PB_TEXT_ON 0x40 |
#define FLAG_PB_VERTICAL_ORIENTATION_OFF 0xfe |
#define FLAG_PB_HORIZONTAL_ORIENTATION_OFF 0xfd |
#define FLAG_PB_FROM_LEFT_TO_RIGHT_OFF 0xfb |
#define FLAG_PB_FROM_RIGHT_TO_LEFT_OFF 0xf7 |
#define FLAG_PB_FROM_DOWN_TO_UP_OFF 0xef |
#define FLAG_PB_FROM_UP_TO_DOWN_OFF 0xdf |
#define FLAG_PB_TEXT_OFF 0xbf |
/programs/develop/libraries/libGUI/SRC/control_progress_bar.inc |
---|
0,0 → 1,320 |
/* |
control ProgressBar |
*/ |
void ProgressBarDrawProgress(struct ControlProgressBar *ProgressBar) |
{ |
int x; |
int y; |
int pos_progress; |
int sizex; |
int sizey; |
char v; |
struct FINITION *fin; |
gui_message_t message; |
gui_text_size_t size; |
gui_text_t *Text; |
if ((ProgressBar->flags & FLAG_SHOW_CONTROL)==FALSE) return; |
x=ProgressBar->ctrl_x; |
y=ProgressBar->ctrl_y; |
sizex=ProgressBar->ctrl_sizex; |
sizey=ProgressBar->ctrl_sizey; |
fin=(struct FINITION*)ProgressBar->finition; |
if (ProgressBar->progress<0.0) ProgressBar->progress=0.0; |
if (ProgressBar->progress>1.0) ProgressBar->progress=1.0; |
v=ProgressBar->prb_flags & FLAG_PB_HORIZONTAL_ORIENTATION_ON; |
if (v!=FALSE) |
{ |
pos_progress=(int)(ProgressBar->progress*(sizex-2)); |
if (ProgressBar->prb_flags & FLAG_PB_FROM_LEFT_TO_RIGHT_ON) |
{ |
Draw(fin,TOOL_GRADIENT_UP_FILLED_RECTANGLE,x+1,y+1,pos_progress,sizey-2,COLOR_FON,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_GRADIENT_UP_FILLED_RECTANGLE,x+1+pos_progress,y+1,sizex-2-pos_progress, |
sizey-2,COLOR_MIDDLE_LIGHT,COLOR_LIGHT); |
if (ProgressBar->prb_flags & FLAG_PB_TEXT_ON) |
{ |
if (fin->flags & FINITION_ON) |
{ |
message.type=MESSAGE_FULL_REDRAW_ALL_WITH_FINITION; |
message.arg1=fin->x; |
message.arg2=fin->y; |
message.arg3=fin->sizex; |
message.arg4=fin->sizey; |
} |
else |
{ |
message.type=MESSAGE_FULL_REDRAW_ALL; |
} |
Text=(gui_text_t*)ProgressBar->child_bk; |
size=GetStringSize((font_t*)Text->font,Text->text); |
Text->ctrl_sizex=(DWORD)size.sizex; |
Text->ctrl_sizey=(DWORD)size.sizey; |
Text->ctrl_x=x+(sizex/2)-(Text->ctrl_sizex/2); |
Text->ctrl_y=y+(sizey/2)-(Text->ctrl_sizey/2); |
SendMessage((struct HEADER*)ProgressBar,&message); |
} |
} |
if (ProgressBar->prb_flags & FLAG_PB_FROM_RIGHT_TO_LEFT_ON) |
{ |
//Draw(fin,"filled_rectangle",x+sizex-pos_progress-1,y+1,x+sizex-1,sizey-2,0xff0000); |
} |
} |
} |
void DrawProgressBar(struct ControlProgressBar *ProgressBar) |
{ |
int x,y,sizex,sizey; |
char c; |
char *save_buf,*buf; |
int save_size_x,save_size_y; |
DWORD draw_output,flags; |
finition_t *fin; |
x=ProgressBar->ctrl_x; |
y=ProgressBar->ctrl_y; |
sizex=ProgressBar->ctrl_sizex; |
sizey=ProgressBar->ctrl_sizey; |
fin=(struct FINITION*)ProgressBar->finition; |
//alocate a buffer for draw text |
c=screen.bits_per_pixel >> 3; |
buf=malloc(sizex*sizey*c); |
//save current screen parameters |
save_buf=screen.buffer; |
save_size_x=screen.size_x; |
save_size_y=screen.size_y; |
draw_output=screen.draw_output; |
//load parameters of local buffer |
screen.buffer=buf; |
screen.size_x=sizex; |
screen.size_y=sizey; |
screen.draw_output=DRAW_OUTPUT_BUFFER; |
//move control |
SetControlNewPosition(ProgressBar,0,0); |
//save finition parameters |
flags=fin->flags; |
fin->flags &=FINITION_OFF; |
//draw progress bar in buffer |
Draw(fin,TOOL_RECTANGLE,0,0,sizex,sizey,COLOR_ABSOLUTE_DARK); |
ProgressBarDrawProgress(ProgressBar); |
//restore last position of control |
SetControlNewPosition(ProgressBar,x,y); |
//restore finition |
fin->flags=flags; |
//restore screen parameters |
screen.buffer=save_buf; |
screen.size_x=save_size_x; |
screen.size_y=save_size_y; |
screen.draw_output=draw_output; |
//move rendered objects from local buffer to screen |
if (fin->flags & FINITION_ON) |
DrawImageFinit(fin,x,y,sizex,sizey,screen.bits_per_pixel,buf); |
else |
DrawImage(x,y,sizex,sizey,screen.bits_per_pixel,buf); |
//free local buffer |
free(buf); |
} |
void SetProgressBarPulse(struct ControlProgressBar *ProgressBar,int time_tick) |
{ |
struct TIMER *timer; |
struct HEADERPARENT *main_parent; |
main_parent=(struct HEADERPARENT*)ProgressBar->main_parent; |
if (main_parent!=(struct HEADERPARENT*)NULL) |
{ |
main_parent->number_timers_for_controls++; |
ProgressBar->timer=(DWORD*)SetTimerCallbackForControl(time_tick,&DrawProgressBar,ProgressBar); |
timer=(struct TIMER*)ProgressBar->timer; |
timer->flags=timer->flags | FLAG_TIMER_ON; |
} |
} |
//--------------------------------------------------------------------------------- |
// control ProgressBar |
//--------------------------------------------------------------------------------- |
void ProgressBarProc(struct ControlProgressBar *ProgressBar,struct MESSAGE *message) |
{ |
int btn_state; |
char v; |
struct TIMER *timer; |
struct FINITION *fin; |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//draw ProgressBar |
if (ProgressBar->flags & FLAG_SHOW_CONTROL) DrawProgressBar(ProgressBar); |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
fin=(struct FINITION*)ProgressBar->finition; |
fin->flags=fin->flags | FINITION_ON; |
fin->x=message->arg1; |
fin->y=message->arg2; |
fin->sizex=message->arg3; |
fin->sizey=message->arg4; |
DrawProgressBar(ProgressBar); |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ //redraw bar of progress |
if (ProgressBar->flags & FLAG_GET_SPECIALIZED_MESSAGE_ON) |
{ |
if (ProgressBar->flags & FLAG_SHOW_CONTROL) ProgressBarDrawProgress(ProgressBar); |
ProgressBar->flags=ProgressBar->flags & FLAG_GET_SPECIALIZED_MESSAGE_OFF; |
} |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
ProgressBar->ctrl_x=ProgressBar->ctrl_x+message->arg1; |
ProgressBar->ctrl_y=ProgressBar->ctrl_y+message->arg2; |
SendMessage((struct HEADER*)ProgressBar,message); |
break; |
} |
case MESSAGE_CALL_TIMER_EVENT: |
{ |
if (ProgressBar->timer!=(DWORD*)NULL) |
{ |
timer=(struct TIMER*)ProgressBar->timer; |
if (timer->flags & FLAG_TIMER_ON) Timer(timer); |
} |
SendMessage((struct HEADER*)ProgressBar,message); |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
if (ProgressBar->timer!=(DWORD*)NULL) free(ProgressBar->timer); |
free(ProgressBar->finition); |
SendMessage((struct HEADER*)ProgressBar,message); |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
SendMessage((struct HEADER*)ProgressBar,message); |
ProgressBar->main_parent=(DWORD*)message->arg1; |
SendMessage((struct HEADER*)ProgressBar,message); |
break; |
} |
default: break; |
} |
} |
//--------------------------------------------------------------------------------- |
// create control ProgressBar |
//--------------------------------------------------------------------------------- |
void* CreateProgressBarEmpty(struct ProgressBarData *info_for_control) |
{ |
struct ControlProgressBar *ProgressBar; |
struct FINITION *fin; |
ProgressBar=malloc(sizeof(struct ControlProgressBar)); |
ProgressBar->finition=malloc(sizeof(struct FINITION)); |
fin=(struct FINITION*)ProgressBar->finition; |
fin->flags=0; |
ID++; |
#ifdef DEBUG |
printf("\ncreated progress bar with ID=%d",(int)ID); |
#endif |
ProgressBar->child_bk=(DWORD*)NULL; |
ProgressBar->child_fd=(DWORD*)NULL; |
ProgressBar->active_control_for_keys=(DWORD*)NULL; |
ProgressBar->active_control_for_mouse=(DWORD*)NULL; |
ProgressBar->callback=(DWORD*)NULL; |
ProgressBar->timer=(DWORD*)NULL; |
ProgressBar->ctrl_proc=(DWORD*)&ProgressBarProc; |
ProgressBar->ctrl_x=(DWORD)info_for_control->x; |
ProgressBar->ctrl_y=(DWORD)info_for_control->y; |
ProgressBar->ctrl_sizex=(DWORD)info_for_control->width; |
ProgressBar->ctrl_sizey=(DWORD)info_for_control->height; |
ProgressBar->ctrl_ID=ID; |
ProgressBar->progress=info_for_control->progress; |
ProgressBar->flags=0; |
ProgressBar->flags=ProgressBar->flags | FLAG_SHOW_CONTROL; |
ProgressBar->prb_flags=0; |
ProgressBar->prb_flags=ProgressBar->prb_flags | FLAG_PB_HORIZONTAL_ORIENTATION_ON; |
ProgressBar->prb_flags=ProgressBar->prb_flags | FLAG_PB_FROM_LEFT_TO_RIGHT_ON; |
return(ProgressBar); |
} |
void* CreateProgressBar(gui_progress_bar_data_t *info) |
{ |
gui_text_t *text; |
gui_text_data_t txtdata; |
gui_progress_bar_t *pbar; |
pbar=CreateProgressBarEmpty(info); |
txtdata.x=0; |
txtdata.y=0; |
txtdata.font=NULL; |
txtdata.background=FALSE; |
txtdata.color=0; |
txtdata.text=malloc(16); |
txtdata.text[0]='\0'; |
text=CreateText(&txtdata); |
text->ctrl_x=pbar->ctrl_sizex/2; |
text->ctrl_y=pbar->ctrl_sizey/2; |
PackControls(pbar,text); |
text->flags &=FLAG_HIDE_CONTROL; |
return(pbar); |
} |
void ProgressBarSetText(gui_progress_bar_t *pbar,char *txt) |
{ |
gui_text_t *text; |
long len1,len2; |
text=(gui_text_t*)pbar->child_bk; |
if (*txt!='\0') |
{ |
len1=strlen(text->text); |
len2=strlen(txt); |
if (len1<len2) |
{ |
free(text->text); |
text->text=malloc(len2+1);//one byte for simbol end of string |
} |
memmove(text->text,txt,len2); |
text->text[len2]='\0'; |
pbar->prb_flags|=FLAG_PB_TEXT_ON; |
text->flags |=FLAG_SHOW_CONTROL; |
} |
} |
char *ProgressBarGetText(gui_progress_bar_t *pbar) |
{ |
gui_text_t *text; |
text=(gui_text_t*)pbar->child_bk; |
return(text->text); |
} |
/programs/develop/libraries/libGUI/SRC/control_scroll_bar.h |
---|
0,0 → 1,6 |
#define FLAG_SCROLL_BAR_ORIENTATION_HORIZONTAL_ON 0x1 |
#define FLAG_SCROLL_BAR_ORIENTATION_HORIZONTAL_OFF 0xfe |
#define FLAG_SCROLL_BAR_ORIENTATION_VERTICAL_ON 0x2 |
#define FLAG_SCROLL_BAR_ORIENTATION_VERTICAL_OFF 0xfd |
#define FLAG_SCROLL_RULLER_PRESSED 0x4 |
#define FLAG_SCROLL_RULLER_RELEASED 0xfb |
/programs/develop/libraries/libGUI/SRC/control_scroll_bar.inc |
---|
0,0 → 1,801 |
/* |
control ScrollBar |
*/ |
//////////////////////////////////////////////////////////////////////////////// |
// Draw Ruller |
//////////////////////////////////////////////////////////////////////////////// |
void DrawRuller(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
int scrollbar_size,ruller_size,ruller_pos; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
if (ScrollBar->scb_flags & FLAG_SCROLL_BAR_ORIENTATION_HORIZONTAL_ON) |
{ |
scrollbar_size=sizex-sizey*2; |
ruller_size=(int)(scrollbar_size*ScrollBar->ruller_size); |
if (ruller_size<5) ruller_size=5; |
if (ruller_size>sizex) ruller_size=sizex-2*sizey; |
ruller_pos=x+sizey+(int)((scrollbar_size-ruller_size)*ScrollBar->ruller_pos); |
//left bar |
Draw(fin,TOOL_FILLED_RECTANGLE,x+sizey,y+1,ruller_pos-x-sizey,sizey-2,COLOR_FON); |
//right bar |
Draw(fin,TOOL_FILLED_RECTANGLE,ruller_pos+ruller_size,y+1,x+sizex-sizey-ruller_pos-ruller_size,sizey-2,COLOR_FON); |
//roller |
Draw(fin,TOOL_RECTANGLE,ruller_pos,y,ruller_size,sizey,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,ruller_pos+1,y+1,ruller_size-2,sizey-2,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_VERTICAL_LINE,ruller_pos+(ruller_size/2)-2,y+sizey/4,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_VERTICAL_LINE,ruller_pos+(ruller_size/2),y+sizey/4,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_VERTICAL_LINE,ruller_pos+(ruller_size/2)+2,y+sizey/4,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
} |
if (ScrollBar->scb_flags & FLAG_SCROLL_BAR_ORIENTATION_VERTICAL_ON) |
{ |
scrollbar_size=sizey-sizex*2; |
ruller_size=(int)(scrollbar_size*ScrollBar->ruller_size); |
if (ruller_size<5) ruller_size=5; |
if (ruller_size>sizey) ruller_size=sizey-2*sizex; |
ruller_pos=y+sizex+(int)((scrollbar_size-ruller_size)*ScrollBar->ruller_pos); |
//up bar |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+sizex,sizex-2,ruller_pos-y-sizex,COLOR_FON); |
//down bar |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,ruller_pos+ruller_size,sizex-2,y+sizey-sizex-ruller_pos-ruller_size,COLOR_FON); |
//roller |
Draw(fin,TOOL_RECTANGLE,x,ruller_pos,sizex,ruller_size,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,ruller_pos+1,sizex-2,ruller_size-2,COLOR_MIDDLE_LIGHT); |
Draw(fin,TOOL_HORIZONTAL_LINE,x+sizex/4,x+(3*sizex)/4,ruller_pos+(ruller_size/2)-2,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_HORIZONTAL_LINE,x+sizex/4,x+(3*sizex)/4,ruller_pos+(ruller_size/2),COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_HORIZONTAL_LINE,x+sizex/4,x+(3*sizex)/4,ruller_pos+(ruller_size/2)+2,COLOR_ABSOLUTE_DARK); |
} |
} |
//////////////////////////////////////////////////////////////////////////////// |
// Draw full Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void DrawScrollBar(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
if (ScrollBar->scb_flags & FLAG_SCROLL_BAR_ORIENTATION_HORIZONTAL_ON) |
{ |
//draw child buttons and roller |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizey,COLOR_ABSOLUTE_DARK); |
//left button |
Draw(fin,TOOL_RECTANGLE,x,y,sizey,sizey,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+1,sizey-2,sizey-2,COLOR_MIDDLE_LIGHT); |
//left arrow of left button |
Draw(fin,TOOL_LINE,x+sizey/3,y+sizey/2,x+(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizey/3,y+sizey/2,x+(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+1+(sizey/3),y+sizey/2,x+1+(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+1+(sizey/3),y+sizey/2,x+1+(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
//right button |
Draw(fin,TOOL_RECTANGLE,x+sizex-sizey,y,sizey,sizey,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+sizex-sizey+1,y+1,sizey-2,sizey-2,COLOR_MIDDLE_LIGHT); |
//right arrow of right button |
Draw(fin,TOOL_LINE,x+sizex-sizey/3,y+sizey/2,x+sizex-(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-sizey/3,y+sizey/2,x+sizex-(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-1-(sizey/3),y+sizey/2,x+sizex-1-(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-1-(sizey/3),y+sizey/2,x+sizex-1-(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
//roller |
DrawRuller(ScrollBar); |
} |
if (ScrollBar->scb_flags & FLAG_SCROLL_BAR_ORIENTATION_VERTICAL_ON) |
{ |
//draw child buttons and roller |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizey,COLOR_ABSOLUTE_DARK); |
//up button |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizex,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+1,sizex-2,sizex-2,COLOR_MIDDLE_LIGHT); |
//up arrow of up button |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizex/3,x+sizex/4,y+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizex/3,x+(3*sizex)/4,y+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+1+(sizex/3),x+sizex/4,y+1+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+1+(sizex/3),x+(3*sizex)/4,y+1+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
//down button |
Draw(fin,TOOL_RECTANGLE,x,y+sizey-sizex,sizex,sizex,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+sizey-sizex+1,sizex-2,sizex-2,COLOR_MIDDLE_LIGHT); |
//down arrow of down button |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-sizex/3,x+sizex/4,y+sizey-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-sizex/3,x+(3*sizex)/4,y+sizey-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-1-(sizex/3),x+sizex/4,y+sizey-1-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-1-(sizex/3),x+(3*sizex)/4,y+sizey-1-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
//roller |
DrawRuller(ScrollBar); |
} |
} |
//////////////////////////////////////////////////////////////////////////////// |
// Vertical Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// animation of up button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_DrawPressedUpButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//up button |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizex,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+1,sizex-2,sizex-2,COLOR_FON); |
//up arrow of up button |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizex/3,x+sizex/4,y+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizex/3,x+(3*sizex)/4,y+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+1+(sizex/3),x+sizex/4,y+1+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+1+(sizex/3),x+(3*sizex)/4,y+1+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
} |
void ScrollBar_DrawReleasedUpButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//up button |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizex,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+1,sizex-2,sizex-2,COLOR_MIDDLE_LIGHT); |
//up arrow of up button |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizex/3,x+sizex/4,y+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizex/3,x+(3*sizex)/4,y+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+1+(sizex/3),x+sizex/4,y+1+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+1+(sizex/3),x+(3*sizex)/4,y+1+(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// animation of down button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_DrawPressedDownButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//down button |
Draw(fin,TOOL_RECTANGLE,x,y+sizey-sizex,sizex,sizex,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+sizey-sizex+1,sizex-2,sizex-2,COLOR_FON); |
//down arrow of down button |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-sizex/3,x+sizex/4,y+sizey-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-sizex/3,x+(3*sizex)/4,y+sizey-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-1-(sizex/3),x+sizex/4,y+sizey-1-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-1-(sizex/3),x+(3*sizex)/4,y+sizey-1-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
} |
void ScrollBar_DrawReleasedDownButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//down button |
Draw(fin,TOOL_RECTANGLE,x,y+sizey-sizex,sizex,sizex,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+sizey-sizex+1,sizex-2,sizex-2,COLOR_MIDDLE_LIGHT); |
//down arrow of down button |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-sizex/3,x+sizex/4,y+sizey-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-sizex/3,x+(3*sizex)/4,y+sizey-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-1-(sizex/3),x+sizex/4,y+sizey-1-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex/2,y+sizey-1-(sizex/3),x+(3*sizex)/4,y+sizey-1-(2*sizex)/3,COLOR_ABSOLUTE_DARK); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// callback function for up button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_FuncCallbackForUpButton_Pressed(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
struct HEADERPARENT *main_parent; |
ScrollBar=(struct ControlScrollBar*)data; |
if (ScrollBar->ruller_size!=1.0) |
{ |
ScrollBar->ruller_pos=ScrollBar->ruller_pos-ScrollBar->ruller_step; |
} |
if (ScrollBar->ruller_pos<0.0) ScrollBar->ruller_pos=0.0; |
ScrollBar_DrawPressedUpButton(ScrollBar); |
if (ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT)!=NULL) |
{ |
main_parent=(struct HEADERPARENT*)ScrollBar->main_parent; |
ScrollBar->flags=ScrollBar->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)ScrollBar; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT); |
main_parent->number_callbacks++; |
} |
DrawRuller(ScrollBar); |
} |
void ScrollBar_FuncCallbackForUpButton_Released(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
ScrollBar=(struct ControlScrollBar*)data; |
ScrollBar_DrawReleasedUpButton(ScrollBar); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// callback function for down button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_FuncCallbackForDownButton_Pressed(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
struct HEADERPARENT *main_parent; |
ScrollBar=(struct ControlScrollBar*)data; |
if (ScrollBar->ruller_size!=1.0) |
{ |
ScrollBar->ruller_pos=ScrollBar->ruller_pos+ScrollBar->ruller_step; |
} |
if (ScrollBar->ruller_pos>1.0) ScrollBar->ruller_pos=1.0; |
ScrollBar_DrawPressedDownButton(ScrollBar); |
if (ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT)!=NULL) |
{ |
main_parent=(struct HEADERPARENT*)ScrollBar->main_parent; |
ScrollBar->flags=ScrollBar->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)ScrollBar; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT); |
main_parent->number_callbacks++; |
} |
DrawRuller(ScrollBar); |
} |
void ScrollBar_FuncCallbackForDownButton_Released(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
ScrollBar=(struct ControlScrollBar*)data; |
ScrollBar_DrawReleasedDownButton(ScrollBar); |
DrawRuller(ScrollBar); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// Horizontal Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// animation of left button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_DrawPressedLeftButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//left button |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+1,sizey-2,sizey-2,COLOR_FON); |
//left arrow of left button |
Draw(fin,TOOL_LINE,x+sizey/3,y+sizey/2,x+(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizey/3,y+sizey/2,x+(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+1+(sizey/3),y+sizey/2,x+1+(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+1+(sizey/3),y+sizey/2,x+1+(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
} |
void ScrollBar_DrawReleasedLeftButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//left button |
Draw(fin,TOOL_FILLED_RECTANGLE,x+1,y+1,sizey-2,sizey-2,COLOR_MIDDLE_LIGHT); |
//left arrow of left button |
Draw(fin,TOOL_LINE,x+sizey/3,y+sizey/2,x+(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizey/3,y+sizey/2,x+(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+1+(sizey/3),y+sizey/2,x+1+(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+1+(sizey/3),y+sizey/2,x+1+(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// animation of right button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_DrawPressedRightButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//right button |
Draw(fin,TOOL_FILLED_RECTANGLE,x+sizex-sizey+1,y+1,sizey-2,sizey-2,COLOR_FON); |
//right arrow of right button |
Draw(fin,TOOL_LINE,x+sizex-sizey/3,y+sizey/2,x+sizex-(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-sizey/3,y+sizey/2,x+sizex-(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-1-(sizey/3),y+sizey/2,x+sizex-1-(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-1-(sizey/3),y+sizey/2,x+sizex-1-(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
} |
void ScrollBar_DrawReleasedRightButton(struct ControlScrollBar *ScrollBar) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
fin=(struct FINITION*)ScrollBar->finition; |
//right button |
Draw(fin,TOOL_FILLED_RECTANGLE,x+sizex-sizey+1,y+1,sizey-2,sizey-2,COLOR_MIDDLE_LIGHT); |
//right arrow of right button |
Draw(fin,TOOL_LINE,x+sizex-sizey/3,y+sizey/2,x+sizex-(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-sizey/3,y+sizey/2,x+sizex-(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-1-(sizey/3),y+sizey/2,x+sizex-1-(2*sizey)/3,y+sizey/4,COLOR_ABSOLUTE_DARK); |
Draw(fin,TOOL_LINE,x+sizex-1-(sizey/3),y+sizey/2,x+sizex-1-(2*sizey)/3,y+(3*sizey)/4,COLOR_ABSOLUTE_DARK); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// callback function for left button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_FuncCallbackForLeftButton_Pressed(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
struct HEADERPARENT *main_parent; |
ScrollBar=(struct ControlScrollBar*)data; |
if (ScrollBar->ruller_size!=1.0) |
{ |
ScrollBar->ruller_pos=ScrollBar->ruller_pos-ScrollBar->ruller_step; |
} |
if (ScrollBar->ruller_pos<0.0) ScrollBar->ruller_pos=0.0; |
ScrollBar_DrawPressedLeftButton(ScrollBar); |
if (ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT)!=NULL) |
{ |
main_parent=(struct HEADERPARENT*)ScrollBar->main_parent; |
ScrollBar->flags=ScrollBar->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)ScrollBar; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT); |
main_parent->number_callbacks++; |
} |
DrawRuller(ScrollBar); |
} |
void ScrollBar_FuncCallbackForLeftButton_Released(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
ScrollBar=(struct ControlScrollBar*)data; |
ScrollBar_DrawReleasedLeftButton(ScrollBar); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// callback function for right button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_FuncCallbackForRightButton_Pressed(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
struct HEADERPARENT *main_parent; |
ScrollBar=(struct ControlScrollBar*)data; |
if (ScrollBar->ruller_size!=1.0) |
{ |
ScrollBar->ruller_pos=ScrollBar->ruller_pos+ScrollBar->ruller_step; |
} |
if (ScrollBar->ruller_pos>1.0) ScrollBar->ruller_pos=1.0; |
ScrollBar_DrawPressedRightButton(ScrollBar); |
if (ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT)!=NULL) |
{ |
main_parent=(struct HEADERPARENT*)ScrollBar->main_parent; |
ScrollBar->flags=ScrollBar->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)ScrollBar; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT); |
main_parent->number_callbacks++; |
} |
DrawRuller(ScrollBar); |
} |
void ScrollBar_FuncCallbackForRightButton_Released(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
ScrollBar=(struct ControlScrollBar*)data; |
ScrollBar_DrawReleasedRightButton(ScrollBar); |
DrawRuller(ScrollBar); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// callback function for ruller bar button of Scroll Bar |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollBar_FuncCallbackForScrollRullerPressed(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
ScrollBar=(struct ControlScrollBar*)data; |
ScrollBar->scb_flags=ScrollBar->scb_flags | FLAG_SCROLL_RULLER_PRESSED; |
} |
void ScrollBar_FuncCallbackForScrollRullerReleased(struct HEADER *control,void *data) |
{ |
struct ControlScrollBar *ScrollBar; |
ScrollBar=(struct ControlScrollBar*)data; |
ScrollBar->scb_flags=ScrollBar->scb_flags & FLAG_SCROLL_RULLER_RELEASED; |
} |
//--------------------------------------------------------------------------------- |
// control ScrollBar |
//--------------------------------------------------------------------------------- |
void ScrollBarProc(struct ControlScrollBar *ScrollBar,struct MESSAGE *message) |
{ |
int mx,my; |
char mouse_buttons_state; |
int x,y,sizex,sizey; |
int scrollbar_size,ruller_size,ruller_pos; |
int ruller_min,ruller_max; |
float max_pos,current_pos,last_ruller_pos; |
struct FINITION *fin; |
struct TIMER *timer; |
struct HEADERPARENT *main_parent; |
x=ScrollBar->ctrl_x; |
y=ScrollBar->ctrl_y; |
sizex=ScrollBar->ctrl_sizex; |
sizey=ScrollBar->ctrl_sizey; |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//draw ScrollBar |
if (ScrollBar->flags & FLAG_SHOW_CONTROL) DrawScrollBar(ScrollBar); |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
fin=(struct FINITION*)ScrollBar->finition; |
fin->flags=fin->flags | FINITION_ON; |
fin->x=message->arg1; |
fin->y=message->arg2; |
fin->sizex=message->arg3; |
fin->sizey=message->arg4; |
DrawScrollBar(ScrollBar); |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ |
if (ScrollBar->flags & FLAG_GET_SPECIALIZED_MESSAGE_ON) |
{ |
if (ScrollBar->flags & FLAG_SHOW_CONTROL) DrawScrollBar(ScrollBar); |
ScrollBar->flags=ScrollBar->flags & FLAG_GET_SPECIALIZED_MESSAGE_OFF; |
} |
break; |
} |
case MESSAGE_MOUSE_EVENT: |
{ |
mx=message->arg1; |
my=message->arg2; |
mouse_buttons_state=message->arg3; |
main_parent=(struct HEADERPARENT*)ScrollBar->main_parent; |
//check ruller state |
if (ScrollBar->scb_flags & FLAG_SCROLL_RULLER_PRESSED) |
{ // horizontal ScrollBar |
if (ScrollBar->scb_flags & FLAG_SCROLL_BAR_ORIENTATION_HORIZONTAL_ON) |
{ |
scrollbar_size=sizex-sizey*2; |
ruller_size=scrollbar_size*ScrollBar->ruller_size; |
if (ruller_size<5) ruller_size=5; |
ruller_min=x+sizey; //minimum x |
ruller_max=ruller_min+scrollbar_size-ruller_size; |
ruller_pos=mx-(ruller_size/2);//ruller centred under mouse pointer |
if (ruller_pos<ruller_min) ruller_pos=ruller_min; |
if (ruller_pos>ruller_max) ruller_pos=ruller_max; |
if (ruller_max!=ruller_min) |
{ |
max_pos=(float)(ruller_max-ruller_min); |
current_pos=(float)(ruller_pos-ruller_min); |
last_ruller_pos=ScrollBar->ruller_pos; |
ScrollBar->ruller_pos=current_pos/max_pos; |
} |
else {ScrollBar->ruller_pos=0.0;} |
if (ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT)!=NULL) |
{ |
if (ScrollBar->ruller_pos!=last_ruller_pos) |
{ |
ScrollBar->flags=ScrollBar->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)ScrollBar; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT); |
main_parent->number_callbacks++; |
} |
} |
if (ScrollBar->ruller_pos!=last_ruller_pos) DrawRuller(ScrollBar); |
break; |
} |
// vertical ScrollBar |
if (ScrollBar->scb_flags & FLAG_SCROLL_BAR_ORIENTATION_VERTICAL_ON) |
{ |
scrollbar_size=sizey-sizex*2; |
ruller_size=scrollbar_size*ScrollBar->ruller_size; |
if (ruller_size<5) ruller_size=5; |
ruller_min=y+sizex; //minimum x |
ruller_max=ruller_min+scrollbar_size-ruller_size; |
ruller_pos=my-(ruller_size/2);//ruller centred under mouse pointer |
if (ruller_pos<ruller_min) ruller_pos=ruller_min; |
if (ruller_pos>ruller_max) ruller_pos=ruller_max; |
if (ruller_max!=ruller_min) |
{ |
max_pos=(float)(ruller_max-ruller_min); |
current_pos=(float)(ruller_pos-ruller_min); |
last_ruller_pos=ScrollBar->ruller_pos; |
ScrollBar->ruller_pos=current_pos/max_pos; |
} |
else {ScrollBar->ruller_pos=0.0;} |
if (ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT)!=NULL) |
{ |
if (ScrollBar->ruller_pos!=last_ruller_pos) |
{ |
ScrollBar->flags=ScrollBar->flags | FLAG_CONNECT_EVENT_ON; |
main_parent->control_for_callback_function[main_parent->number_callbacks]= |
(DWORD*)ScrollBar; |
main_parent->callback_for_control_callback[main_parent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(ScrollBar,SCROLLBAR_CHANGED_EVENT); |
main_parent->number_callbacks++; |
} |
} |
if (ScrollBar->ruller_pos!=last_ruller_pos) DrawRuller(ScrollBar); |
} |
} |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
ScrollBar->ctrl_x=ScrollBar->ctrl_x+message->arg1; |
ScrollBar->ctrl_y=ScrollBar->ctrl_y+message->arg2; |
break; |
} |
case MESSAGE_CALL_TIMER_EVENT: |
{ |
if (ScrollBar->timer!=(DWORD*)NULL) |
{ |
timer=(struct TIMER*)ScrollBar->timer; |
if (timer->flags & FLAG_TIMER_ON) Timer(timer); |
} |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
if (ScrollBar->timer!=(DWORD*)NULL) free(ScrollBar->timer); |
free(ScrollBar->finition); |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
SendMessage((struct HEADER*)ScrollBar,message); |
ScrollBar->main_parent=(DWORD*)message->arg1; |
break; |
} |
default: break; |
} |
//send message to child controls(if there is) |
SendMessage((struct HEADER*)ScrollBar,message); |
} |
//--------------------------------------------------------------------------------- |
// create control ScrollBar |
//--------------------------------------------------------------------------------- |
void* CreateScrollBar(struct ScrollBarData *info_for_control) |
{ |
struct ControlScrollBar *ScrollBar; |
struct FINITION *fin; |
ScrollBar=malloc(sizeof(struct ControlScrollBar)); |
ScrollBar->finition=malloc(sizeof(struct FINITION)); |
fin=(struct FINITION*)ScrollBar->finition; |
fin->flags=0; |
ID++; |
#ifdef DEBUG |
printf("\ncreated scroll bar with ID=%d",(int)ID); |
#endif |
ScrollBar->child_bk=(DWORD*)NULL; |
ScrollBar->child_fd=(DWORD*)NULL; |
ScrollBar->active_control_for_keys=(DWORD*)NULL; |
ScrollBar->active_control_for_mouse=(DWORD*)NULL; |
ScrollBar->callback=(DWORD*)NULL; |
ScrollBar->timer=(DWORD*)NULL; |
ScrollBar->ctrl_proc=(DWORD*)&ScrollBarProc; |
ScrollBar->ctrl_x=(DWORD)info_for_control->x; |
ScrollBar->ctrl_y=(DWORD)info_for_control->y; |
ScrollBar->ctrl_sizex=(DWORD)info_for_control->width; |
ScrollBar->ctrl_sizey=(DWORD)info_for_control->height; |
ScrollBar->ctrl_ID=ID; |
ScrollBar->ruller_size=info_for_control->ruller_size; |
ScrollBar->ruller_pos=info_for_control->ruller_pos; |
ScrollBar->ruller_step=info_for_control->ruller_step; |
ScrollBar->flags=0; |
ScrollBar->flags=ScrollBar->flags | FLAG_SHOW_CONTROL; |
return(ScrollBar); |
} |
void* CreateHorizontalScrollBar(struct ScrollBarData *info_for_control) |
{ |
struct ControlScrollBar *ScrollBar; |
struct ControlButton *ChildButton1; |
struct ControlButton *ChildButton2; |
struct ControlButton *ScrollRuller; |
struct ButtonData ChildButton1Data; |
struct ButtonData ChildButton2Data; |
struct ButtonData ScrollRullerData; |
ScrollBar=CreateScrollBar(info_for_control); |
//set horizontal orientation |
ScrollBar->scb_flags=0; |
ScrollBar->scb_flags=ScrollBar->scb_flags | FLAG_SCROLL_BAR_ORIENTATION_HORIZONTAL_ON; |
//fill data for first child button of scroller |
ChildButton1Data.x=0; |
ChildButton1Data.y=0; |
ChildButton1Data.width=ScrollBar->ctrl_sizey; |
ChildButton1Data.height=ChildButton1Data.width; |
//fill data for second child button of scroller |
ChildButton2Data.x=ScrollBar->ctrl_sizex-ScrollBar->ctrl_sizey; |
ChildButton2Data.y=0; |
ChildButton2Data.width=ScrollBar->ctrl_sizey; |
ChildButton2Data.height=ChildButton2Data.width; |
//fill data for scroll ruller button of scroller |
ScrollRullerData.x=ScrollBar->ctrl_sizey; |
ScrollRullerData.y=0; |
ScrollRullerData.width=ScrollBar->ctrl_sizex-2*ScrollBar->ctrl_sizey; |
ScrollRullerData.height=ScrollBar->ctrl_sizey; |
ChildButton1=CreateButton(&ChildButton1Data); |
ChildButton2=CreateButton(&ChildButton2Data); |
ScrollRuller=CreateButton(&ScrollRullerData); |
ChildButton1->flags=ChildButton1->flags & FLAG_HIDE_CONTROL; |
ChildButton2->flags=ChildButton2->flags & FLAG_HIDE_CONTROL; |
ScrollRuller->flags=ScrollRuller->flags & FLAG_HIDE_CONTROL; |
SetCallbackFunction(ChildButton1,BUTTON_PRESSED_EVENT,&ScrollBar_FuncCallbackForLeftButton_Pressed,ScrollBar); |
SetCallbackFunction(ChildButton1,BUTTON_RELEASED_EVENT,&ScrollBar_FuncCallbackForLeftButton_Released,ScrollBar); |
SetCallbackFunction(ChildButton2,BUTTON_PRESSED_EVENT,&ScrollBar_FuncCallbackForRightButton_Pressed,ScrollBar); |
SetCallbackFunction(ChildButton2,BUTTON_RELEASED_EVENT,&ScrollBar_FuncCallbackForRightButton_Released,ScrollBar); |
SetCallbackFunction(ScrollRuller,BUTTON_PRESSED_EVENT,&ScrollBar_FuncCallbackForScrollRullerPressed,ScrollBar); |
SetCallbackFunction(ScrollRuller,BUTTON_RELEASED_EVENT,&ScrollBar_FuncCallbackForScrollRullerReleased,ScrollBar); |
//pack button in control ScrollBar |
PackControls(ScrollBar,ChildButton1); |
PackControls(ScrollBar,ChildButton2); |
PackControls(ScrollBar,ScrollRuller); |
return(ScrollBar); |
} |
void* CreateVerticalScrollBar(struct ScrollBarData *info_for_control) |
{ |
struct ControlScrollBar *ScrollBar; |
struct ControlButton *ChildButton1; |
struct ControlButton *ChildButton2; |
struct ControlButton *ScrollRuller; |
struct ButtonData ChildButton1Data; |
struct ButtonData ChildButton2Data; |
struct ButtonData ScrollRullerData; |
ScrollBar=CreateScrollBar(info_for_control); |
//set vertical orientation |
ScrollBar->scb_flags=0; |
ScrollBar->scb_flags=ScrollBar->scb_flags | FLAG_SCROLL_BAR_ORIENTATION_VERTICAL_ON; |
//fill data for first child button of scroller |
ChildButton1Data.x=0; |
ChildButton1Data.y=0; |
ChildButton1Data.width=ScrollBar->ctrl_sizex; |
ChildButton1Data.height=ChildButton1Data.width; |
//fill data for second child button of scroller |
ChildButton2Data.x=0; |
ChildButton2Data.y=ScrollBar->ctrl_sizey-ScrollBar->ctrl_sizex; |
ChildButton2Data.width=ScrollBar->ctrl_sizex; |
ChildButton2Data.height=ChildButton2Data.width; |
//fill data for scroll ruller button of scroller |
ScrollRullerData.x=0; |
ScrollRullerData.y=ScrollBar->ctrl_sizex; |
ScrollRullerData.width=ScrollBar->ctrl_sizex; |
ScrollRullerData.height=ScrollBar->ctrl_sizey-2*ScrollBar->ctrl_sizex; |
ChildButton1=CreateButton(&ChildButton1Data); |
ChildButton2=CreateButton(&ChildButton2Data); |
ScrollRuller=CreateButton(&ScrollRullerData); |
ChildButton1->flags=ChildButton1->flags & FLAG_HIDE_CONTROL; |
ChildButton2->flags=ChildButton2->flags & FLAG_HIDE_CONTROL; |
ScrollRuller->flags=ScrollRuller->flags & FLAG_HIDE_CONTROL; |
SetCallbackFunction(ChildButton1,BUTTON_PRESSED_EVENT,&ScrollBar_FuncCallbackForUpButton_Pressed,ScrollBar); |
SetCallbackFunction(ChildButton1,BUTTON_RELEASED_EVENT,&ScrollBar_FuncCallbackForUpButton_Released,ScrollBar); |
SetCallbackFunction(ChildButton2,BUTTON_PRESSED_EVENT,&ScrollBar_FuncCallbackForDownButton_Pressed,ScrollBar); |
SetCallbackFunction(ChildButton2,BUTTON_RELEASED_EVENT,&ScrollBar_FuncCallbackForDownButton_Released,ScrollBar); |
SetCallbackFunction(ScrollRuller,BUTTON_PRESSED_EVENT,&ScrollBar_FuncCallbackForScrollRullerPressed,ScrollBar); |
SetCallbackFunction(ScrollRuller,BUTTON_RELEASED_EVENT,&ScrollBar_FuncCallbackForScrollRullerReleased,ScrollBar); |
//pack button in control ScrollBar |
PackControls(ScrollBar,ChildButton1); |
PackControls(ScrollBar,ChildButton2); |
PackControls(ScrollBar,ScrollRuller); |
return(ScrollBar); |
} |
/programs/develop/libraries/libGUI/SRC/control_scrolled_window.h |
---|
0,0 → 1,6 |
#define FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON 0x1 |
#define FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON 0x2 |
#define FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_OFF 0xfe |
#define FLAG_SCROLL_WIN_VERTICAL_SCROLL_OFF 0xfd |
/programs/develop/libraries/libGUI/SRC/control_scrolled_window.inc |
---|
0,0 → 1,530 |
/* |
control ScrolledWindow |
*/ |
//////////////////////////////////////////////////////////////////////// |
// pack controls in ScrolledWindow |
//////////////////////////////////////////////////////////////////////// |
void ScrolledWindowPackControls(void *parent,void *Control) |
{ |
struct HEADER *control; |
struct ControlScrolledWindow *ScrolledWindow; |
struct ControlScrollBar *HorizontalScrollBar; |
struct ControlScrollBar *VerticalScrollBar; |
struct FINITION *fin; |
int x,y; |
ScrolledWindow=(struct ControlScrolledWindow*)parent; |
control=(struct HEADER *)Control; |
if (control->ctrl_x+control->ctrl_sizex>ScrolledWindow->virtual_sizex) |
{ |
ScrolledWindow->virtual_sizex=control->ctrl_x+control->ctrl_sizex; |
} |
if (control->ctrl_y+control->ctrl_sizey>ScrolledWindow->virtual_sizey) |
{ |
ScrolledWindow->virtual_sizey=control->ctrl_y+control->ctrl_sizey; |
} |
PackControls(ScrolledWindow,control); |
//calculate new control coordinates |
x=control->ctrl_x+1;//add border width |
y=control->ctrl_y+1;//add border heght |
SetControlNewPosition(control,x,y); |
//save coordinates of control in arrea |
ScrolledWindow->virtual_controls_x[ScrolledWindow->number_virtual_controls]=x; |
ScrolledWindow->virtual_controls_y[ScrolledWindow->number_virtual_controls]=y; |
ScrolledWindow->number_virtual_controls++; |
x=ScrolledWindow->ctrl_x+1; |
y=ScrolledWindow->ctrl_y+1; |
//check cross control with scroll arrea |
if (CheckCrossRectangles(x,y,ScrolledWindow->scroll_arrea_sizex,ScrolledWindow->scroll_arrea_sizey, |
control->ctrl_x,control->ctrl_y,control->ctrl_sizex,control->ctrl_sizey)==TRUE) |
{ |
control->flags=control->flags | FLAG_SHOW_CONTROL; |
control->flags=control->flags & FLAG_MOUSE_BLOCKED_OFF; |
} |
else |
{ |
control->flags=control->flags & FLAG_HIDE_CONTROL; |
control->flags=control->flags | FLAG_MOUSE_BLOCKED_ON; |
} |
if (ScrolledWindow->virtual_sizex>ScrolledWindow->scroll_arrea_sizex) |
{ |
HorizontalScrollBar=(struct ControlScrollBar*)ScrolledWindow->horizontal_scroll; |
if ((ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON)==FALSE) |
{ |
ScrolledWindow->scroll_arrea_sizey=ScrolledWindow->ctrl_sizey-16-2; |
ScrolledWindow->scw_flags=ScrolledWindow->scw_flags | FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON; |
HorizontalScrollBar->flags=HorizontalScrollBar->flags | FLAG_SHOW_CONTROL; |
HorizontalScrollBar->flags=HorizontalScrollBar->flags & FLAG_MOUSE_BLOCKED_OFF; |
} |
} |
if (ScrolledWindow->virtual_sizey>ScrolledWindow->scroll_arrea_sizey) |
{ |
VerticalScrollBar=(struct ControlScrollBar*)ScrolledWindow->vertical_scroll; |
if ((ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON)==FALSE) |
{ |
ScrolledWindow->scroll_arrea_sizex=ScrolledWindow->ctrl_sizex-16-2; |
ScrolledWindow->scw_flags=ScrolledWindow->scw_flags | FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON; |
VerticalScrollBar->flags=VerticalScrollBar->flags | FLAG_SHOW_CONTROL; |
VerticalScrollBar->flags=VerticalScrollBar->flags & FLAG_MOUSE_BLOCKED_OFF; |
} |
} |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON) |
{ |
HorizontalScrollBar->ruller_size=(float)ScrolledWindow->scroll_arrea_sizex; |
HorizontalScrollBar->ruller_size=HorizontalScrollBar->ruller_size/((float)ScrolledWindow->virtual_sizex); |
} |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON) |
{ |
VerticalScrollBar->ruller_size=(float)ScrolledWindow->scroll_arrea_sizey; |
VerticalScrollBar->ruller_size=VerticalScrollBar->ruller_size/((float)ScrolledWindow->virtual_sizey); |
} |
//finit draw arrea for control |
fin=(struct FINITION*)control->finition; |
fin->x=ScrolledWindow->ctrl_x+1; |
fin->y=ScrolledWindow->ctrl_y+1; |
fin->sizex=ScrolledWindow->scroll_arrea_sizex; |
fin->sizey=ScrolledWindow->scroll_arrea_sizey; |
fin->flags=fin->flags | FINITION_ON; |
} |
//////////////////////////////////////////////////////////////////////////////// |
// Draw full Scrolled Window |
//////////////////////////////////////////////////////////////////////////////// |
void ScrollWin_FuncCallback_HVScroll(struct HEADER* control,void *data) |
{ |
struct ControlScrollBar *Hscrollbar,*Vscrollbar; |
struct ControlScrolledWindow *ScrolledWindow; |
struct HEADER *seek_control,*exchange_control; |
struct MESSAGE local_message; |
struct FINITION *fin; |
int i,new_x,new_y,x,y,sizex,sizey; |
char c; |
char *save_buf,*buf; |
int save_size_x,save_size_y; |
DWORD draw_output; |
ScrolledWindow=(gui_scrolled_window_t*)data; |
Hscrollbar=(gui_scroll_bar_t*)ScrolledWindow->horizontal_scroll; |
Vscrollbar=(gui_scroll_bar_t*)ScrolledWindow->vertical_scroll; |
ScrolledWindow->virtual_x=(ScrolledWindow->virtual_sizex-ScrolledWindow->scroll_arrea_sizex)*Hscrollbar->ruller_pos; |
ScrolledWindow->virtual_y=(ScrolledWindow->virtual_sizey-ScrolledWindow->scroll_arrea_sizey)*Vscrollbar->ruller_pos; |
x=ScrolledWindow->ctrl_x+1; |
y=ScrolledWindow->ctrl_y+1; |
sizex=ScrolledWindow->scroll_arrea_sizex; |
sizey=ScrolledWindow->scroll_arrea_sizey; |
//alocate a buffer for draw text |
c=screen.bits_per_pixel >> 3; |
i=sizex*sizey*c; |
buf=malloc(i); |
//save current screen parameters |
save_buf=screen.buffer; |
save_size_x=screen.size_x; |
save_size_y=screen.size_y; |
draw_output=screen.draw_output; |
//load parameters of local buffer |
screen.buffer=buf; |
screen.size_x=sizex; |
screen.size_y=sizey; |
screen.draw_output=DRAW_OUTPUT_BUFFER; |
//fill buffer by background color |
FillArrea(buf,i,screen.bits_per_pixel,COLOR_LIGHT); |
local_message.type=MESSAGE_FULL_REDRAW_ALL_WITH_FINITION; |
local_message.arg1=0; |
local_message.arg2=0; |
local_message.arg3=sizex; |
local_message.arg4=sizey; |
seek_control=(struct HEADER*)Vscrollbar->ctrl_fd; |
//move controls in new position |
for(i=0;i<ScrolledWindow->number_virtual_controls;i++) |
{ |
new_x=ScrolledWindow->virtual_controls_x[i]-ScrolledWindow->virtual_x; |
new_y=ScrolledWindow->virtual_controls_y[i]-ScrolledWindow->virtual_y; |
SetControlNewPosition(seek_control,new_x,new_y); |
if (CheckCrossRectangles(x,y,sizex,sizey,new_x,new_y, |
seek_control->ctrl_sizex, |
seek_control->ctrl_sizey)==TRUE) |
{ |
seek_control->flags=seek_control->flags | FLAG_SHOW_CONTROL; |
seek_control->flags=seek_control->flags & FLAG_MOUSE_BLOCKED_OFF; |
//move control |
SetControlNewPosition(seek_control,new_x-x,new_y-y); |
//call draw control in buffer |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,&local_message); |
//restore last position of control |
SetControlNewPosition(seek_control,new_x,new_y); |
//restore coordinates of last finition of control |
fin=(finition_t*)seek_control->finition; |
fin->x=x; |
fin->y=y; |
} |
else |
{ |
seek_control->flags=seek_control->flags & FLAG_HIDE_CONTROL; |
seek_control->flags=seek_control->flags | FLAG_MOUSE_BLOCKED_ON; |
} |
exchange_control=(struct HEADER*)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
//restore screen parameters |
screen.buffer=save_buf; |
screen.size_x=save_size_x; |
screen.size_y=save_size_y; |
screen.draw_output=draw_output; |
//move rendered objects from local buffer to screen |
fin=(finition_t*)ScrolledWindow->finition; |
if (fin->flags & FINITION_ON) |
DrawImageFinit(fin,x,y,sizex,sizey,screen.bits_per_pixel,buf); |
else |
DrawImage(x,y,sizex,sizey,screen.bits_per_pixel,buf); |
//free local buffer |
free(buf); |
} |
void DrawScrolledWindow(struct ControlScrolledWindow *ScrolledWindow) |
{ |
int x,y,sizex,sizey; |
struct FINITION *fin; |
x=ScrolledWindow->ctrl_x; |
y=ScrolledWindow->ctrl_y; |
sizex=ScrolledWindow->ctrl_sizex; |
sizey=ScrolledWindow->ctrl_sizey; |
fin=(struct FINITION*)ScrolledWindow->finition; |
if ((ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON) || |
(ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON)) |
{ |
Draw(fin,TOOL_RECTANGLE,x,y,ScrolledWindow->scroll_arrea_sizex+2, |
ScrolledWindow->scroll_arrea_sizey+2,COLOR_ABSOLUTE_DARK); |
} |
else |
Draw(fin,TOOL_RECTANGLE,x,y,sizex,sizey,COLOR_ABSOLUTE_DARK); |
ScrollWin_FuncCallback_HVScroll(NULL,ScrolledWindow); |
} |
void ScrlWinCheckActivatedForKeysControl(struct ControlScrolledWindow *ScrolledWindow) |
{ |
struct HEADER *control,*seek_control,*exchange_control; |
struct MESSAGE local_message; |
struct FINITION *fin; |
struct ControlScrollBar *Vscrollbar,*Hscrollbar; |
int i,x,y,sizex,sizey; |
int sx,sy; |
control=(struct HEADER*)ScrolledWindow->active_control_for_keys; |
x=ScrolledWindow->ctrl_x+1; |
y=ScrolledWindow->ctrl_y+1; |
sizex=ScrolledWindow->scroll_arrea_sizex; |
sizey=ScrolledWindow->scroll_arrea_sizey; |
if (CheckFullCrossRectangles(x,y,sizex,sizey, |
control->ctrl_x,control->ctrl_y,control->ctrl_sizex,control->ctrl_sizey)==TRUE) return; |
//calculate new x and y coordinates |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON) |
{ |
sx=(control->ctrl_x-x); |
if (sx<0) sx=x; |
else |
{ |
if (control->ctrl_sizex<sizex) sx=x+sizex-control->ctrl_sizex; |
else sx=x; |
} |
} |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON) |
{ |
sy=(control->ctrl_y-y); |
if (sy<0) sy=y; |
else |
{ |
if (control->ctrl_sizey<sizey) sy=y+sizey-control->ctrl_sizey; |
else sy=y; |
} |
} |
Vscrollbar=(struct ControlScrollBar*)ScrolledWindow->vertical_scroll; |
Hscrollbar=(struct ControlScrollBar*)ScrolledWindow->horizontal_scroll; |
//find active control and virtual control coordinates |
seek_control=(struct HEADER*)Vscrollbar->ctrl_fd; |
for(i=0;i<ScrolledWindow->number_virtual_controls;i++) |
{ |
if (seek_control==control) |
{ |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON) |
ScrolledWindow->virtual_x=ScrolledWindow->virtual_controls_x[i]-sx; |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON) |
ScrolledWindow->virtual_y=ScrolledWindow->virtual_controls_y[i]-sy; |
break; |
} |
exchange_control=(struct HEADER*)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_HORIZONTAL_SCROLL_ON) |
{ |
Hscrollbar->ruller_pos=(float)ScrolledWindow->virtual_x; |
Hscrollbar->ruller_pos=Hscrollbar->ruller_pos/((float)(ScrolledWindow->virtual_sizex-ScrolledWindow->scroll_arrea_sizex)); |
SpecialRedrawControl(Hscrollbar); |
} |
if (ScrolledWindow->scw_flags & FLAG_SCROLL_WIN_VERTICAL_SCROLL_ON) |
{ |
Vscrollbar->ruller_pos=(float)ScrolledWindow->virtual_y; |
Vscrollbar->ruller_pos=Vscrollbar->ruller_pos/((float)(ScrolledWindow->virtual_sizey-ScrolledWindow->scroll_arrea_sizey)); |
SpecialRedrawControl(Vscrollbar); |
} |
ScrollWin_FuncCallback_HVScroll(NULL,ScrolledWindow); |
} |
//--------------------------------------------------------------------------------- |
// control ScrolledWindowScrolledWindow->virtual_sizex |
//--------------------------------------------------------------------------------- |
void ScrolledWindowProc(struct ControlScrolledWindow *ScrolledWindow,struct MESSAGE *message) |
{ |
int i,x,y,sizex,sizey; |
struct HEADER *seek_control,*exchange_control; |
struct ControlScrollBar *Hscrollbar,*Vscrollbar; |
struct MESSAGE local_message; |
struct FINITION *fin; |
struct TIMER *timer; |
x=ScrolledWindow->ctrl_x; |
y=ScrolledWindow->ctrl_y; |
sizex=ScrolledWindow->ctrl_sizex; |
sizey=ScrolledWindow->ctrl_sizey; |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//draw ScrolledWindow |
if (ScrolledWindow->flags & FLAG_SHOW_CONTROL) |
{ |
DrawScrolledWindow(ScrolledWindow); |
Hscrollbar=(gui_scroll_bar_t*)ScrolledWindow->horizontal_scroll; |
Vscrollbar=(gui_scroll_bar_t*)ScrolledWindow->vertical_scroll; |
//draw scroll bars |
ControlProc=(void (*)(void *Control,gui_message_t *message))Hscrollbar->ctrl_proc; |
ControlProc(Hscrollbar,message); |
ControlProc=(void (*)(void *Control,gui_message_t *message))Vscrollbar->ctrl_proc; |
ControlProc(Vscrollbar,message); |
} |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
fin=(struct FINITION*)ScrolledWindow->finition; |
fin->flags=fin->flags | FINITION_ON; |
fin->x=message->arg1; |
fin->y=message->arg2; |
fin->sizex=message->arg3; |
fin->sizey=message->arg4; |
DrawScrolledWindow(ScrolledWindow); |
SendMessage((struct HEADER*)ScrolledWindow,message);//<<<<<<---------------------------------- |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ |
if (ScrolledWindow->flags & FLAG_SHOW_CONTROL) SendMessage((struct HEADER*)ScrolledWindow,message); |
ScrolledWindow->flags=ScrolledWindow->flags & FLAG_GET_SPECIALIZED_MESSAGE_OFF; |
break; |
} |
case MESSAGE_KEYS_EVENT: |
{ |
if (ScrolledWindow->active_control_for_keys!=NULL) ScrlWinCheckActivatedForKeysControl(ScrolledWindow); |
SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_MOUSE_EVENT: |
{ |
SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
ScrolledWindow->ctrl_x=ScrolledWindow->ctrl_x+message->arg1; |
ScrolledWindow->ctrl_y=ScrolledWindow->ctrl_y+message->arg2; |
//change virtual coordinates of controls |
Vscrollbar=(struct ControlScrollBar*)ScrolledWindow->vertical_scroll; |
seek_control=(struct HEADER *)Vscrollbar->ctrl_fd; |
for(i=0;i<ScrolledWindow->number_virtual_controls;i++) |
{ |
ScrolledWindow->virtual_controls_x[i]+=message->arg1; |
ScrolledWindow->virtual_controls_y[i]+=message->arg2; |
fin=(struct FINITION*)seek_control->finition; |
fin->x=ScrolledWindow->ctrl_x+1; |
fin->y=ScrolledWindow->ctrl_y+1; |
fin->sizex=ScrolledWindow->scroll_arrea_sizex; |
fin->sizey=ScrolledWindow->scroll_arrea_sizey; |
exchange_control=(struct HEADER*)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_CALL_TIMER_EVENT: |
{ |
if (ScrolledWindow->timer!=(DWORD*)NULL) |
{ |
timer=(struct TIMER*)ScrolledWindow->timer; |
if (timer->flags & FLAG_TIMER_ON) Timer(timer); |
} |
SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_SET_FOCUSE: |
{ |
//SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_CHANGE_FOCUSE: |
{ |
//SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
if (ScrolledWindow->timer!=(DWORD*)NULL) free(ScrolledWindow->timer); |
free(ScrolledWindow->finition); |
SendMessage((struct HEADER*)ScrolledWindow,message); |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
SendMessage((struct HEADER*)ScrolledWindow,message); |
ScrolledWindow->main_parent=(DWORD*)message->arg1; |
break; |
} |
default: break; |
} |
} |
//--------------------------------------------------------------------------------- |
// create control ScrolledWindow |
//--------------------------------------------------------------------------------- |
void* CreateScrolledWindow(struct ScrolledWindowData *info_for_control) |
{ |
struct ControlScrolledWindow *ScrolledWindow; |
struct FINITION *fin; |
struct ControlScrollBar *HorizontalScrollBar; |
struct ControlScrollBar *VerticalScrollBar; |
struct ScrollBarData HorizontalScrollData; |
struct ScrollBarData VerticalScrollData; |
ScrolledWindow=malloc(sizeof(struct ControlScrolledWindow)); |
ScrolledWindow->finition=malloc(sizeof(struct FINITION)); |
fin=(struct FINITION*)ScrolledWindow->finition; |
fin->flags=0; |
ScrolledWindow->scw_flags=0; |
ID++; |
#ifdef DEBUG |
printf("\ncreated scrollet window with ID=%d",(int)ID); |
#endif |
ScrolledWindow->child_bk=(DWORD*)NULL; |
ScrolledWindow->child_fd=(DWORD*)NULL; |
ScrolledWindow->active_control_for_keys=(DWORD*)NULL; |
ScrolledWindow->active_control_for_mouse=(DWORD*)NULL; |
ScrolledWindow->callback=(DWORD*)NULL; |
ScrolledWindow->timer=(DWORD*)NULL; |
ScrolledWindow->ctrl_proc=(DWORD*)&ScrolledWindowProc; |
ScrolledWindow->ctrl_x=(DWORD)info_for_control->x; |
ScrolledWindow->ctrl_y=(DWORD)info_for_control->y; |
ScrolledWindow->ctrl_sizex=(DWORD)info_for_control->width; |
ScrolledWindow->ctrl_sizey=(DWORD)info_for_control->height; |
ScrolledWindow->ctrl_ID=ID; |
ScrolledWindow->virtual_x=0; |
ScrolledWindow->virtual_y=0; |
ScrolledWindow->virtual_controls_x=malloc(1024*sizeof(DWORD)); |
ScrolledWindow->virtual_controls_y=malloc(1024*sizeof(DWORD)); |
ScrolledWindow->virtual_sizex=0; |
ScrolledWindow->virtual_sizey=0; |
ScrolledWindow->number_virtual_controls=0; |
ScrolledWindow->flags=0; |
ScrolledWindow->flags=ScrolledWindow->flags | FLAG_SHOW_CONTROL; |
ScrolledWindow->flags=ScrolledWindow->flags | FLAG_FOCUSE_INPUT_SUPPOROTE; |
//calculate default scroll arrea size |
ScrolledWindow->scroll_arrea_sizex=ScrolledWindow->ctrl_sizex-2; |
ScrolledWindow->scroll_arrea_sizey=ScrolledWindow->ctrl_sizey-2; |
//create child scroll bars |
HorizontalScrollData.x=0; |
HorizontalScrollData.y=ScrolledWindow->ctrl_sizey-16; |
HorizontalScrollData.width=ScrolledWindow->ctrl_sizex-16; |
HorizontalScrollData.height=16; |
HorizontalScrollData.ruller_size=1.0; |
HorizontalScrollData.ruller_pos=0.0; |
HorizontalScrollData.ruller_step=0.05; |
VerticalScrollData.x=ScrolledWindow->ctrl_sizex-16; |
VerticalScrollData.y=0; |
VerticalScrollData.width=16; |
VerticalScrollData.height=ScrolledWindow->ctrl_sizey-16; |
VerticalScrollData.ruller_size=1.0; |
VerticalScrollData.ruller_pos=0.0; |
VerticalScrollData.ruller_step=0.05; |
HorizontalScrollBar=CreateHorizontalScrollBar(&HorizontalScrollData); |
VerticalScrollBar=CreateVerticalScrollBar(&VerticalScrollData); |
SetCallbackFunction(HorizontalScrollBar,SCROLLBAR_CHANGED_EVENT,&ScrollWin_FuncCallback_HVScroll,ScrolledWindow); |
SetCallbackFunction(VerticalScrollBar,SCROLLBAR_CHANGED_EVENT,&ScrollWin_FuncCallback_HVScroll,ScrolledWindow); |
PackControls(ScrolledWindow,HorizontalScrollBar); |
PackControls(ScrolledWindow,VerticalScrollBar); |
ScrolledWindow->horizontal_scroll=(DWORD*)HorizontalScrollBar; |
ScrolledWindow->vertical_scroll=(DWORD*)VerticalScrollBar; |
//disable show scrollers and block mouse for them |
HorizontalScrollBar->flags=HorizontalScrollBar->flags & FLAG_HIDE_CONTROL; |
HorizontalScrollBar->flags=HorizontalScrollBar->flags | FLAG_MOUSE_BLOCKED_ON; |
VerticalScrollBar->flags=VerticalScrollBar->flags & FLAG_HIDE_CONTROL; |
VerticalScrollBar->flags=VerticalScrollBar->flags | FLAG_MOUSE_BLOCKED_ON; |
return(ScrolledWindow); |
} |
/programs/develop/libraries/libGUI/SRC/control_text.h |
---|
0,0 → 1,16 |
#define TEXT_ORIENTATION_FROM_LEFT_TO_RIGHT_ON 0x1 |
#define TEXT_ORIENTATION_FROM_LEFT_TO_RIGHT_OFF 0xfe |
#define TEXT_BACKGROUND_ON 0x2; |
#define TEXT_BACKGROUND_OFF 0xfd; |
struct TextSize |
{ |
int sizex; |
int sizey; |
}; |
typedef struct TextSize gui_text_size_t; |
/programs/develop/libraries/libGUI/SRC/control_text.inc |
---|
0,0 → 1,182 |
/* |
control Text |
*/ |
gui_text_size_t GetStringSize(font_t *font,char *s) |
{ |
long len; |
gui_text_size_t size; |
len=strlen(s); |
if (font->size==FONT_CONSTANT_SIZE) |
{ |
if (font->flags & FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_ON) |
{ |
size.sizex=len*font->sizex; |
size.sizey=font->sizey; |
} |
} |
return(size); |
} |
void TextBackgroundOn(gui_text_t *Text) |
{ |
Text->txt_flags |=TEXT_BACKGROUND_ON; |
} |
void TextBackgroundOff(gui_text_t *Text) |
{ |
Text->txt_flags &=TEXT_BACKGROUND_ON; |
} |
void DisplayText(gui_text_t *Text) |
{ |
int x; |
int y; |
int sizex; |
int sizey; |
char v; |
font_t *font; |
gui_text_size_t size; |
struct FINITION *fin; |
x=Text->ctrl_x; |
y=Text->ctrl_y; |
fin=(struct FINITION*)Text->finition; |
font=(font_t*)Text->font; |
v=Text->txt_flags & TEXT_BACKGROUND_ON; |
if (v) font->flags|=FONT_FLAG_DRAW_BACKGROUND_ON; |
else font->flags&=FONT_FLAG_DRAW_BACKGROUND_OFF; |
v=Text->txt_flags & TEXT_ORIENTATION_FROM_LEFT_TO_RIGHT_ON; |
if (v) font->flags|=FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_ON; |
else font->flags&=FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_OFF; |
//recalculate size of control text befor draw |
size=GetStringSize((font_t*)Text->font,Text->text); |
Text->ctrl_sizex=(DWORD)size.sizex; |
Text->ctrl_sizey=(DWORD)size.sizey; |
DrawFont=(void(*)(finition_t *fin,int fx,int fy,DWORD color, |
DWORD background_color,font_t *font,BYTE *s))font->fnt_draw; |
DrawFont(fin,x,y,Text->color,Text->background_color,font,Text->text); |
} |
//--------------------------------------------------------------------------------- |
// control Text |
//--------------------------------------------------------------------------------- |
void TextProc(gui_text_t *Text,gui_message_t *message) |
{ |
finition_t *fin; |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//draw Text |
if (Text->flags & FLAG_SHOW_CONTROL) DisplayText(Text); |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
fin=(struct FINITION*)Text->finition; |
fin->flags=fin->flags | FINITION_ON; |
fin->x=message->arg1; |
fin->y=message->arg2; |
fin->sizex=message->arg3; |
fin->sizey=message->arg4; |
DisplayText(Text); |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ |
if (Text->flags & FLAG_GET_SPECIALIZED_MESSAGE_ON) |
{ |
if (Text->flags & FLAG_SHOW_CONTROL) DisplayText(Text); |
Text->flags=Text->flags & FLAG_GET_SPECIALIZED_MESSAGE_OFF; |
} |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
Text->ctrl_x=Text->ctrl_x+message->arg1; |
Text->ctrl_y=Text->ctrl_y+message->arg2; |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
free(Text->finition); |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
SendMessage((struct HEADER*)Text,message); |
Text->main_parent=(DWORD*)message->arg1; |
break; |
} |
default: break; |
} |
//send message to child controls(if there is) |
SendMessage((struct HEADER*)Text,message); |
} |
//--------------------------------------------------------------------------------- |
// create control Text |
//--------------------------------------------------------------------------------- |
void* CreateText(gui_text_data_t *info_for_control) |
{ |
gui_text_t *Text; |
finition_t *fin; |
gui_text_size_t size; |
Text=malloc(sizeof(struct ControlText)); |
Text->finition=malloc(sizeof(struct FINITION)); |
fin=(struct FINITION*)Text->finition; |
fin->flags=0; |
if (info_for_control->font==(DWORD*)NULL) Text->font=FontsMeneger.default_font; |
else Text->font=info_for_control->font; |
size=GetStringSize((font_t*)Text->font,info_for_control->text); |
ID++; |
#ifdef DEBUG |
printf("\ncreated text with ID=%d",(int)ID); |
#endif |
Text->child_bk=(DWORD*)NULL; |
Text->child_fd=(DWORD*)NULL; |
Text->active_control_for_keys=(DWORD*)NULL; |
Text->active_control_for_mouse=(DWORD*)NULL; |
Text->callback=(DWORD*)NULL; |
Text->timer=(DWORD*)NULL; |
Text->ctrl_proc=(DWORD*)&TextProc; |
Text->ctrl_x=(DWORD)info_for_control->x; |
Text->ctrl_y=(DWORD)info_for_control->y; |
Text->ctrl_sizex=(DWORD)size.sizex; |
Text->ctrl_sizey=(DWORD)size.sizey; |
Text->ctrl_ID=ID; |
Text->color=info_for_control->color; |
Text->background_color=info_for_control->background_color; |
Text->text=info_for_control->text; |
Text->txt_flags=0; |
Text->txt_flags|=TEXT_ORIENTATION_FROM_LEFT_TO_RIGHT_ON; |
if (info_for_control->background) |
{ |
Text->txt_flags|=TEXT_BACKGROUND_ON; |
} |
else |
{ |
Text->txt_flags&=TEXT_BACKGROUND_OFF; |
} |
Text->flags=0; |
Text->flags=Text->flags | FLAG_SHOW_CONTROL; |
return(Text); |
} |
/programs/develop/libraries/libGUI/SRC/draw_controls.h |
---|
0,0 → 1,31 |
#define FINITION_ON 0x1 |
#define FINITION_OFF 0xfe |
#define COLOR_FON 0x924900 |
#define COLOR_DARK 0x5a5a5a |
#define COLOR_ABSOLUTE_DARK 0x0 |
#define COLOR_MIDDLE_LIGHT 0xffff00 |
#define COLOR_LIGHT 0xffffff |
#define COLOR_INSERT 0x71ff30//0xffff10 |
///////////////////////////////////////////////////////////////////////////////////////// |
// tool's names |
///////////////////////////////////////////////////////////////////////////////////////// |
#define TOOL_PIXEL 128 |
#define TOOL_LINE 129 |
#define TOOL_VERTICAL_LINE 130 |
#define TOOL_HORIZONTAL_LINE 131 |
#define TOOL_RECTANGLE 132 |
#define TOOL_FILLED_RECTANGLE 133 |
#define TOOL_GRADIENT_UP_FILLED_RECTANGLE 134 |
#define TOOL_GRADIENT_DOWN_FILLED_RECTANGLE 135 |
#define TOOL_GRADIENT_LEFT_FILLED_RECTANGLE 136 |
#define TOOL_GRADIENT_RIGHT_FILLED_RECTANGLE 137 |
#define TOOL_CIRCLE 138 |
#define TOOL_FILLED_CIRCLE 139 |
#define TOOL_ELLIPSE 140 |
#define TOOL_FILLED_ELLIPSE 141 |
#define TOOL_IMAGE 142 |
/programs/develop/libraries/libGUI/SRC/draw_controls.inc |
---|
0,0 → 1,2149 |
/* |
functions for draw controls |
*/ |
//--------------------------------------------------------------------------------- |
// fill buffer by value |
//--------------------------------------------------------------------------------- |
void FillArrea(void *buf,DWORD size,BYTE bits_per_pixel,DWORD value) |
{ |
DWORD i,j; |
char r,g,b; |
switch(bits_per_pixel) |
{ |
case 32: |
{ |
j=(size >> 2); |
for(i=0;i<j;i++) |
{ |
*(DWORD*)buf=(DWORD)value; |
buf=(DWORD*)buf+1; |
} |
break; |
} |
case 24: |
{ |
b=value & 0xff; |
value=value >> 8; |
g=value & 0xff; |
value=value >> 8; |
r=value & 0xff; |
j=(size/3); |
for(i=0;i<j;i++) |
{ |
*(char*)buf=(char)b; |
*((char*)buf+1)=(char)g; |
*((char*)buf+2)=(char)r; |
buf=(char*)buf+3; |
} |
break; |
} |
case 16: |
{ |
break; |
} |
case 8: |
{ |
break; |
} |
case 4: |
{ |
break; |
} |
default: break; |
} |
} |
//--------------------------------------------------------------------------------- |
// draw pixel on screen |
//--------------------------------------------------------------------------------- |
void DrawPixel(int x,int y,DWORD color) |
{ |
char r,g,b; |
char *ptr; |
DWORD *ptr2; |
if (x>screen.size_x-1) {x=screen.size_x-1;} |
if (y>screen.size_y-1) {y=screen.size_y-1;} |
if (x<0) {x=0;} |
if (y<0) {y=0;} |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
x+=screen.x; |
y+=screen.y; |
gui_ksys_put_pixel_window(x,y,color); |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
ptr=screen.buffer; |
switch(screen.bits_per_pixel) |
{ |
case 24: |
{ |
ptr=ptr+(y*screen.size_x+x)*3; |
b=color & 0xff; |
color=color >>8; |
g=color & 0xff; |
color=color >>8; |
r=color & 0xff; |
ptr[0]=b; |
ptr[1]=g; |
ptr[2]=r; |
break; |
} |
case 32: |
{ |
ptr2=(DWORD*)ptr+y*screen.size_x+x; |
*ptr2=color; |
break; |
} |
default: break; |
} |
break; |
} |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing pixels on screen with finition |
//--------------------------------------------------------------------------------- |
void DrawPixelFinit(struct FINITION *fin,int x,int y,DWORD color) |
{ |
if (x>=fin->x && x<=fin->x+fin->sizex-1 && |
y>=fin->y && y<=fin->y+fin->sizey-1) DrawPixel(x,y,color); |
} |
//--------------------------------------------------------------------------------- |
// get color of pixel inc coordinates x,y |
//--------------------------------------------------------------------------------- |
DWORD GetColorPixel(int x,int y) |
{ |
char r,g,b; |
char *ptr; |
DWORD color,coordinates; |
DWORD *ptr2; |
if (x>screen.size_x-1) {x=screen.size_x-1;} |
if (y>screen.size_y-1) {y=screen.size_y-1;} |
if (x<0) {x=0;} |
if (y<0) {y=0;} |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
x+=screen.x; |
y+=screen.y; |
coordinates=x; |
coordinates=coordinates << 16; |
coordinates +=y; |
color=gui_ksys_get_color_pixel_window(coordinates); |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
ptr=screen.buffer; |
switch(screen.bits_per_pixel) |
{ |
case 24: |
{ |
ptr=ptr+(y*screen.size_x+x)*3; |
color=*ptr; |
color=color & 0xffffff; |
break; |
} |
case 32: |
{ |
ptr2=(DWORD*)ptr+y*screen.size_x+x; |
color=*ptr2; |
break; |
} |
default: break; |
} |
} |
} |
return(color); |
} |
//--------------------------------------------------------------------------------- |
// draw vertical line on screen |
//--------------------------------------------------------------------------------- |
void DrawVerticalLine(int x,int y1,int y2,DWORD color) |
{ |
char r,g,b; |
char *ptr; |
DWORD *ptr2; |
int a,i,count; |
if (x>screen.size_x-1) {x=screen.size_x-1;} |
if (y1>screen.size_y-1) {y1=screen.size_y-1;} |
if (y2>screen.size_y-1) {y2=screen.size_y-1;} |
if (x<0) {x=0;} |
if (y1<0) {y1=0;} |
if (y2<0) {y2=0;} |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
x+=screen.x; |
y1+=screen.y; |
y2+=screen.y; |
gui_ksys_draw_line_window(x,y1,x,y2,color); |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
if (y1<y2) {a=y1;count=y2-y1;} |
else |
{a=y2;count=y1-y2;} |
ptr=screen.buffer; |
switch(screen.bits_per_pixel) |
{ |
case 24: |
{ |
ptr=ptr+(a*screen.size_x+x)*3; |
b=color & 0xff; |
color=color >>8; |
g=color & 0xff; |
color=color >>8; |
r=color & 0xff; |
a=screen.size_x*3; |
for(i=0;i<=count;i++) |
{ |
ptr[0]=b; |
ptr[1]=g; |
ptr[2]=r; |
ptr+=a; |
} |
break; |
} |
case 32: |
{ |
ptr2=(DWORD*)ptr+a*screen.size_x+x; |
a=screen.size_x; |
for(i=0;i<=count;i++) |
{ |
*ptr2=color; |
ptr2+=a; |
} |
break; |
} |
default: break; |
} |
} |
} |
} |
//--------------------------------------------------------------------------------- |
// draw finited vertical line on screen |
//--------------------------------------------------------------------------------- |
void DrawVerticalLineFinit(struct FINITION *fin,int x,int y1,int y2,DWORD color) |
{ |
int xmin,xmax,ymin,ymax,v,sy; |
xmin=fin->x; |
xmax=fin->x+fin->sizex-1; |
ymin=fin->y; |
ymax=fin->y+fin->sizey-1; |
if (y2<y1) |
{ |
v=y1; |
y1=y2; |
y2=v; |
} |
if (x<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y1>ymax) return; |
//finit x coordinates and sizex |
sy=y1-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y1=ymin; |
if (y2>ymax) y2=ymax; |
} |
DrawVerticalLine(x,y1,y2,color); |
} |
//--------------------------------------------------------------------------------- |
// draw horizontal line on screen |
//--------------------------------------------------------------------------------- |
void DrawHorizontalLine(int x1,int x2,int y,DWORD color) |
{ |
char r,g,b; |
char *ptr; |
int a,i,count; |
DWORD *ptr2; |
if (y>screen.size_y-1) {y=screen.size_y-1;} |
if (x1>screen.size_x-1) {x1=screen.size_x-1;} |
if (x2>screen.size_x-1) {x2=screen.size_x-1;} |
if (y<0) {y=0;} |
if (x1<0) {x1=0;} |
if (x2<0) {x2=0;} |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
x1+=screen.x; |
x2+=screen.x; |
y+=screen.y; |
gui_ksys_draw_line_window(x1,y,x2,y,color); |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
if (x1<x2) {a=x1;count=x2-x1;} |
else |
{a=x2;count=x1-x2;} |
ptr=screen.buffer; |
switch(screen.bits_per_pixel) |
{ |
case 24: |
{ |
ptr=ptr+(y*screen.size_x+a)*3; |
b=color & 0xff; |
color=color >>8; |
g=color & 0xff; |
color=color >>8; |
r=color & 0xff; |
for(i=0;i<=count;i++) |
{ |
ptr[0]=b; |
ptr[1]=g; |
ptr[2]=r; |
ptr=ptr+3; |
} |
break; |
} |
case 32: |
{ |
ptr2=(DWORD*)ptr+y*screen.size_x+a; |
for(i=0;i<=count;i++) |
{ |
*ptr2=color;ptr2++; |
} |
break; |
} |
default:break; |
} |
} |
} |
} |
//--------------------------------------------------------------------------------- |
// draw finited vertical line on screen |
//--------------------------------------------------------------------------------- |
void DrawHorizontalLineFinit(struct FINITION *fin,int x1,int x2,int y,DWORD color) |
{ |
int xmin,xmax,ymin,ymax,v,sx; |
xmin=fin->x; |
xmax=fin->x+fin->sizex-1; |
ymin=fin->y; |
ymax=fin->y+fin->sizey-1; |
if (x2<x1) |
{ |
v=x1; |
x1=x2; |
x2=v; |
} |
if (y<ymin) return; |
if (y>ymax) return; |
if (x2<xmin) return; |
if (x1>xmax) return; |
//finit x coordinates and sizex |
sx=x1-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x1=xmin; |
if (x2>xmax) x2=xmax; |
} |
DrawHorizontalLine(x1,x2,y,color); |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing line on screen |
//--------------------------------------------------------------------------------- |
int sign(int value) |
{ |
if (value==0) return(0); |
if (value<0) {return(-1);} |
else {return(1);} |
} |
int abs(int value) |
{ |
if (value<0) {value=-value;} |
return(value); |
} |
void DrawLine(int x1, int y1, int x2, int y2,DWORD color) |
{ |
int x; |
int y; |
int dx; |
int dy; |
int sx; |
int sy; |
int z; |
int e; |
int i; |
char ch; |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
if (y1>screen.size_y-1) {y1=screen.size_y-1;} |
if (y2>screen.size_y-1) {y2=screen.size_y-1;} |
if (x1>screen.size_x-1) {x1=screen.size_x-1;} |
if (x2>screen.size_x-1) {x2=screen.size_x-1;} |
if (y1<0) {y1=0;} |
if (y2<0) {y2=0;} |
if (x1<0) {x1=0;} |
if (x2<0) {x2=0;} |
x1+=screen.x; |
x2+=screen.x; |
y1+=screen.y; |
y2+=screen.y; |
gui_ksys_draw_line_window(x1,y1,x2,y2,color); |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
x = x1; |
y = y1; |
dx = abs(x2-x1); |
dy = abs(y2-y1); |
sx = sign(x2-x1); |
sy = sign(y2-y1); |
if( dx==0 && dy==0 ) |
{ |
DrawPixel(x1, y1,color); |
return; |
} |
if( dy>dx ) |
{ |
z = dx; |
dx = dy; |
dy = z; |
ch = 1; |
} |
else |
{ |
ch = 0; |
} |
e = 2*dy-dx; |
i = 1; |
do |
{ |
DrawPixel(x,y,color); |
while(e>=0) |
{ |
if( ch==1 ) x = x+sx; |
else y = y+sy; |
if( ch==1 ) y = y+sy; |
else x = x+sx; |
e = e-2*dx; |
} |
if( ch==1 ) y = y+sy; |
else x = x+sx; |
e = e+2*dy; |
i++; |
} |
while(i<=dx); |
DrawPixel(x, y,color); |
break; |
} |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing rectangle on screen |
//--------------------------------------------------------------------------------- |
void DrawRectangle(int x,int y,int size_x,int size_y,DWORD color) |
{ |
if (size_x==0 || size_y==0) return; |
DrawHorizontalLine(x,x+size_x-1,y,color); |
DrawVerticalLine(x+size_x-1,y,y+size_y-1,color); |
DrawHorizontalLine(x,x+size_x-1,y+size_y-1,color); |
DrawVerticalLine(x,y,y+size_y-1,color); |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing finited rectangle on screen |
//--------------------------------------------------------------------------------- |
void DrawRectangleFinit(struct FINITION *fin,int x,int y,int size_x,int size_y,DWORD color) |
{ |
if (size_x==0 || size_y==0) return; |
DrawHorizontalLineFinit(fin,x,x+size_x-1,y,color); |
DrawVerticalLineFinit(fin,x+size_x-1,y,y+size_y-1,color); |
DrawHorizontalLineFinit(fin,x,x+size_x-1,y+size_y-1,color); |
DrawVerticalLineFinit(fin,x,y,y+size_y-1,color); |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled rectangle on screen |
//--------------------------------------------------------------------------------- |
void DrawFilledRectangle(int x,int y,int size_x,int size_y,DWORD color) |
{ |
int i,j; |
int x1,y1,x2,y2; |
if (size_x==0 || size_y==0) return; |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
x1=x; |
y1=y; |
x2=x+size_x-1; |
y2=y+size_y-1; |
if (y1>screen.size_y-1) {y1=screen.size_y-1;} |
if (y2>screen.size_y-1) {y2=screen.size_y-1;} |
if (x1>screen.size_x-1) {x1=screen.size_x-1;} |
if (x2>screen.size_x-1) {x2=screen.size_x-1;} |
if (y1<0) {y1=0;} |
if (y2<0) {y2=0;} |
if (x1<0) {x1=0;} |
if (x2<0) {x2=0;} |
size_x=x2-x1+1; |
size_y=y2-y1+1; |
x1+=screen.x; |
y1+=screen.y; |
gui_ksys_draw_filled_rectangle_window(x1,y1,size_x,size_y,color); |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
j=y; |
for(i=0;i<size_y;i++) |
{ |
DrawHorizontalLine(x,x+size_x-1,j,color); |
j++; |
} |
break; |
} |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled gradient up and down rectangles on screen |
//--------------------------------------------------------------------------------- |
void DrawGradientUpDownFilledRectangle(char flag_up,int x,int y,int sizex,int sizey,DWORD color_from,DWORD color_to) |
{ |
unsigned char r_f,g_f,b_f; |
unsigned char r_t,g_t,b_t; |
unsigned char r,g,b; |
float f_r,f_g,f_b; |
float d_r,d_g,d_b; |
float div; |
DWORD color; |
int i,j,dj; |
if (sizex==0 || sizey==0) return; |
color=color_from; |
b_f=color & 0xff; |
color=color >> 8; |
g_f=color & 0xff; |
color=color >> 8; |
r_f=color & 0xff; |
color=color_to; |
b_t=color & 0xff; |
color=color >> 8; |
g_t=color & 0xff; |
color=color >> 8; |
r_t=color & 0xff; |
div=sizey-1; |
d_r=(float)(r_t-r_f); |
d_r=d_r/div; |
d_g=(float)(g_t-g_f); |
d_g=d_g/div; |
d_b=(float)(b_t-b_f); |
d_b=d_b/div; |
f_r=r_f; |
f_g=g_f; |
f_b=b_f; |
r=r_f; |
g=g_f; |
b=b_f; |
if (flag_up==TRUE) |
{ |
j=y+sizey-1; |
dj=-1; |
} |
else |
{ |
j=y; |
dj=1; |
} |
for(i=0;i<sizey;i++) |
{ |
color=0; |
color=color | r; |
color=color << 8; |
color=color | g; |
color=color << 8; |
color=color | b; |
DrawHorizontalLine(x,x+sizex-1,j,color); |
f_r=f_r+d_r; |
f_g=f_g+d_g; |
f_b=f_b+d_b; |
r=(char)f_r; |
g=(char)f_g; |
b=(char)f_b; |
j=j+dj; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled gradient left and right rectangles on screen |
//--------------------------------------------------------------------------------- |
void DrawGradientLeftRightFilledRectangle(char flag_left,int x,int y,int sizex,int sizey,DWORD color_from,DWORD color_to) |
{ |
unsigned char r_f,g_f,b_f; |
unsigned char r_t,g_t,b_t; |
unsigned char r,g,b; |
float f_r,f_g,f_b; |
float d_r,d_g,d_b; |
float div; |
DWORD color; |
int i,j,dj; |
if (sizex==0 || sizey==0) return; |
color=color_from; |
b_f=color & 0xff; |
color=color >> 8; |
g_f=color & 0xff; |
color=color >> 8; |
r_f=color & 0xff; |
color=color_to; |
b_t=color & 0xff; |
color=color >> 8; |
g_t=color & 0xff; |
color=color >> 8; |
r_t=color & 0xff; |
div=sizex-1; |
d_r=(float)(r_t-r_f); |
d_r=d_r/div; |
d_g=(float)(g_t-g_f); |
d_g=d_g/div; |
d_b=(float)(b_t-b_f); |
d_b=d_b/div; |
f_r=r_f; |
f_g=g_f; |
f_b=b_f; |
r=r_f; |
g=g_f; |
b=b_f; |
if (flag_left==TRUE) |
{ |
j=x; |
dj=1; |
} |
else |
{ |
j=x+sizex-1; |
dj=-1; |
} |
for(i=0;i<sizex;i++) |
{ |
color=0; |
color=color | r; |
color=color << 8; |
color=color | g; |
color=color << 8; |
color=color | b; |
DrawVerticalLine(j,y,y+sizey-1,color); |
f_r=f_r+d_r; |
f_g=f_g+d_g; |
f_b=f_b+d_b; |
r=(char)f_r; |
g=(char)f_g; |
b=(char)f_b; |
j=j+dj; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing circle on screen |
//--------------------------------------------------------------------------------- |
void DrawCircle(int xc, int yc, int r,DWORD color) |
{ |
int x; |
int y; |
int d; |
x = 0; |
y = r; |
d = 3-2*r; |
while(y>=x) |
{ |
DrawPixel(x+xc,y+yc,color); |
DrawPixel(x+xc,-y+yc,color); |
DrawPixel(-x+xc,y+yc,color); |
DrawPixel(-x+xc,-y+yc,color); |
DrawPixel(y+xc,x+yc,color); |
DrawPixel(y+xc,-x+yc,color); |
DrawPixel(-y+xc,x+yc,color); |
DrawPixel(-y+xc,-x+yc,color); |
if( d<0 ) |
{ |
d = d+4*x+6; |
} |
else |
{ |
d = d+4*(x-y)+10; |
y--; |
} |
x++; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing circle on screen with finition |
//--------------------------------------------------------------------------------- |
void DrawCircleFinit(struct FINITION *fin,int xc, int yc, int r,DWORD color) |
{ |
int x; |
int y; |
int d; |
x = 0; |
y = r; |
d = 3-2*r; |
while(y>=x) |
{ |
DrawPixelFinit(fin,x+xc,y+yc,color); |
DrawPixelFinit(fin,x+xc,-y+yc,color); |
DrawPixelFinit(fin,-x+xc,y+yc,color); |
DrawPixelFinit(fin,-x+xc,-y+yc,color); |
DrawPixelFinit(fin,y+xc,x+yc,color); |
DrawPixelFinit(fin,y+xc,-x+yc,color); |
DrawPixelFinit(fin,-y+xc,x+yc,color); |
DrawPixelFinit(fin,-y+xc,-x+yc,color); |
if( d<0 ) |
{ |
d = d+4*x+6; |
} |
else |
{ |
d = d+4*(x-y)+10; |
y--; |
} |
x++; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled circle on screen |
//--------------------------------------------------------------------------------- |
void DrawFilledCircle(int xc, int yc, int r,DWORD color) |
{ |
int xl,yu,xr,yd; |
int i,j; |
DWORD pixcolor; |
DrawCircle(xc,yc,r,color); |
yu=yc; |
yd=yc; |
for(i=0;i<r;i++) |
{ |
xl=xc; |
xr=xc+1; |
j=0; |
//fill left up |
while((pixcolor=GetColorPixel(xl,yu))!=color) |
{ |
DrawPixel(xl,yu,color); |
xl--; |
j++; |
if (j>r) break; |
} |
j=0; |
//fill right up |
while((pixcolor=GetColorPixel(xr,yu))!=color) |
{ |
DrawPixel(xr,yu,color); |
xr++; |
j++; |
if (j>r) break; |
} |
xl=xc; |
xr=xc+1; |
j=0; |
//fill left down |
while((pixcolor=GetColorPixel(xl,yd))!=color) |
{ |
DrawPixel(xl,yd,color); |
xl--; |
j++; |
if (j>r) break; |
} |
j=0; |
//fill right down |
while((pixcolor=GetColorPixel(xr,yd))!=color) |
{ |
DrawPixel(xr,yd,color); |
xr++; |
j++; |
if (j>r) break; |
} |
yu--; |
yd++; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled circle on screen with finition |
//--------------------------------------------------------------------------------- |
void DrawFilledCircleFinit(struct FINITION *fin,int xc, int yc, int r,DWORD color) |
{ |
int xl,yu,xr,yd; |
int i,j; |
DWORD pixcolor; |
DrawCircleFinit(fin,xc,yc,r,color); |
yu=yc; |
yd=yc; |
for(i=0;i<r;i++) |
{ |
xl=xc; |
xr=xc+1; |
//fill left up |
for(j=0;j<r;j++) |
{ |
if (xl>=fin->x && xl<=fin->x+fin->sizex && |
yu>=fin->y && yu<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xl,yu); |
if (pixcolor!=color) DrawPixel(xl,yu,color); |
else break; |
} |
xl--; |
} |
//fill right up |
for(j=0;j<r;j++) |
{ |
if (xr>=fin->x && xr<=fin->x+fin->sizex && |
yu>=fin->y && yu<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xr,yu); |
if (pixcolor!=color) DrawPixel(xr,yu,color); |
else break; |
} |
xr++; |
} |
xl=xc; |
xr=xc+1; |
//fill left down |
for(j=0;j<r;j++) |
{ |
if (xl>=fin->x && xl<=fin->x+fin->sizex && |
yd>=fin->y && yd<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xl,yd); |
if (pixcolor!=color) DrawPixel(xl,yd,color); |
else break; |
} |
xl--; |
} |
//fill right down |
for(j=0;j<r;j++) |
{ |
if (xr>=fin->x && xr<=fin->x+fin->sizex && |
yd>=fin->y && yd<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xr,yd); |
if (pixcolor!=color) DrawPixel(xr,yd,color); |
else break; |
} |
xr++; |
} |
yu--; |
yd++; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing ellipse on screen |
//--------------------------------------------------------------------------------- |
void DrawEllipse(int x,int y,int a,int b,DWORD color) |
{ |
int col,i,row,bnew; |
long a_square,b_square,two_a_square,two_b_square,four_a_square,four_b_square,d; |
b_square=b*b; |
a_square=a*a; |
row=b; |
col=0; |
two_a_square=a_square<<1; |
four_a_square=a_square<<2; |
four_b_square=b_square<<2; |
two_b_square=b_square<<1; |
d=two_a_square*((row-1)*(row))+a_square+two_b_square*(1-a_square); |
while(a_square*(row)>b_square*(col)) |
{ |
DrawPixel(col+x,row+y,color); |
DrawPixel(col+x,y-row,color); |
DrawPixel(x-col,row+y,color); |
DrawPixel(x-col,y-row,color); |
if (d>=0) |
{ |
row--; |
d-=four_a_square*(row); |
} |
d+=two_b_square*(3+(col<<1)); |
col++; |
} |
d=two_b_square*(col+1)*col+two_a_square*(row*(row-2)+1)+(1-two_a_square)*b_square; |
while ((row) + 1) |
{ |
DrawPixel(col+x, row+y, color); |
DrawPixel(col+x, y-row, color); |
DrawPixel(x-col, row+y, color); |
DrawPixel(x-col, y-row, color); |
if (d<=0) |
{ |
col++; |
d+=four_b_square*col; |
} |
row--; |
d+=two_a_square*(3-(row <<1)); |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing ellipse on screen with finition |
//--------------------------------------------------------------------------------- |
void DrawEllipseFinit(struct FINITION *fin,int x,int y,int a,int b,DWORD color) |
{ |
int col,i,row,bnew; |
long a_square,b_square,two_a_square,two_b_square,four_a_square,four_b_square,d; |
b_square=b*b; |
a_square=a*a; |
row=b; |
col=0; |
two_a_square=a_square<<1; |
four_a_square=a_square<<2; |
four_b_square=b_square<<2; |
two_b_square=b_square<<1; |
d=two_a_square*((row-1)*(row))+a_square+two_b_square*(1-a_square); |
while(a_square*(row)>b_square*(col)) |
{ |
DrawPixelFinit(fin,col+x,row+y,color); |
DrawPixelFinit(fin,col+x,y-row,color); |
DrawPixelFinit(fin,x-col,row+y,color); |
DrawPixelFinit(fin,x-col,y-row,color); |
if (d>=0) |
{ |
row--; |
d-=four_a_square*(row); |
} |
d+=two_b_square*(3+(col<<1)); |
col++; |
} |
d=two_b_square*(col+1)*col+two_a_square*(row*(row-2)+1)+(1-two_a_square)*b_square; |
while ((row) + 1) |
{ |
DrawPixelFinit(fin,col+x, row+y, color); |
DrawPixelFinit(fin,col+x, y-row, color); |
DrawPixelFinit(fin,x-col, row+y, color); |
DrawPixelFinit(fin,x-col, y-row, color); |
if (d<=0) |
{ |
col++; |
d+=four_b_square*col; |
} |
row--; |
d+=two_a_square*(3-(row <<1)); |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled ellips on screen |
//--------------------------------------------------------------------------------- |
void DrawFilledEllipse(int xc, int yc, int a,int b,DWORD color) |
{ |
int xl,yu,xr,yd; |
int i,j; |
DWORD pixcolor; |
DrawEllipse(xc,yc,a,b,color); |
yu=yc; |
yd=yc; |
for(i=0;i<b;i++) |
{ |
xl=xc; |
xr=xc+1; |
j=0; |
//fill left up |
while((pixcolor=GetColorPixel(xl,yu))!=color) |
{ |
DrawPixel(xl,yu,color); |
xl--; |
j++; |
if (j>a) break; |
} |
j=0; |
//fill right up |
while((pixcolor=GetColorPixel(xr,yu))!=color) |
{ |
DrawPixel(xr,yu,color); |
xr++; |
j++; |
if (j>a) break; |
} |
xl=xc; |
xr=xc+1; |
j=0; |
//fill left down |
while((pixcolor=GetColorPixel(xl,yd))!=color) |
{ |
DrawPixel(xl,yd,color); |
xl--; |
j++; |
if (j>a) break; |
} |
j=0; |
//fill right down |
while((pixcolor=GetColorPixel(xr,yd))!=color) |
{ |
DrawPixel(xr,yd,color); |
xr++; |
j++; |
if (j>a) break; |
} |
yu--; |
yd++; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing filled circle on screen with finition |
//--------------------------------------------------------------------------------- |
void DrawFilledEllipseFinit(struct FINITION *fin,int xc, int yc, int a,int b,DWORD color) |
{ |
int xl,yu,xr,yd; |
int i,j; |
DWORD pixcolor; |
DrawEllipseFinit(fin,xc,yc,a,b,color); |
yu=yc; |
yd=yc; |
for(i=0;i<b;i++) |
{ |
xl=xc; |
xr=xc+1; |
//fill left up |
for(j=0;j<a;j++) |
{ |
if (xl>=fin->x && xl<=fin->x+fin->sizex && |
yu>=fin->y && yu<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xl,yu); |
if (pixcolor!=color) DrawPixel(xl,yu,color); |
else break; |
} |
xl--; |
} |
//fill right up |
for(j=0;j<a;j++) |
{ |
if (xr>=fin->x && xr<=fin->x+fin->sizex && |
yu>=fin->y && yu<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xr,yu); |
if (pixcolor!=color) DrawPixel(xr,yu,color); |
else break; |
} |
xr++; |
} |
xl=xc; |
xr=xc+1; |
//fill left down |
for(j=0;j<a;j++) |
{ |
if (xl>=fin->x && xl<=fin->x+fin->sizex && |
yd>=fin->y && yd<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xl,yd); |
if (pixcolor!=color) DrawPixel(xl,yd,color); |
else break; |
} |
xl--; |
} |
//fill right down |
for(j=0;j<a;j++) |
{ |
if (xr>=fin->x && xr<=fin->x+fin->sizex && |
yd>=fin->y && yd<=fin->y+fin->sizey) |
{ |
pixcolor=GetColorPixel(xr,yd); |
if (pixcolor!=color) DrawPixel(xr,yd,color); |
else break; |
} |
xr++; |
} |
yu--; |
yd++; |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing image on screen |
//--------------------------------------------------------------------------------- |
void DrawImage(int x,int y,int sizex,int sizey,char bits_per_pixel,char *img) |
{ |
char r,g,b; |
int i,j,countx,county; |
int x2,y2; |
DWORD pitch_src,pitch_screen,add_src,add_screen; |
char *ptr_src,*ptr_screen,ptr_max; |
char *ptr_src2,*ptr_screen2; |
DWORD *ptr_src3; |
if (img==NULL) return; |
if (x>screen.size_x-1) return; |
if (y>screen.size_y-1) return; |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (y2>screen.size_y-1) {y2=screen.size_y-1;} |
if (x2>screen.size_x-1) {x2=screen.size_x-1;} |
if (y<0) y=0; |
if (y2<0) y2=0; |
if (x<0) x=0; |
if (x2<0) x2=0; |
countx=x2-x+1; |
county=y2-y+1; |
switch(screen.draw_output) |
{ |
case DRAW_OUTPUT_SCREEN: |
{ |
x+=screen.x; |
y+=screen.y; |
switch(screen.bits_per_pixel) |
{ |
case 32: |
case 24: |
{ |
switch(bits_per_pixel) |
{//check bits per pixel in picture |
case 32: |
{//convert 32 bit image to 24 bit image |
j=sizex*sizey; |
ptr_src=img; |
ptr_screen=malloc(j*3); |
ptr_screen2=ptr_screen; |
for(i=0;i<j;i++) |
{ |
*(char*)ptr_screen=*(char*)ptr_src; |
*((char*)ptr_screen+1)=*((char*)ptr_src+1); |
*((char*)ptr_screen+2)=*((char*)ptr_src+2); |
ptr_src+=4; |
ptr_screen+=3; |
} |
gui_ksys_put_image_window(ptr_screen2,x,y,countx,county); |
free(ptr_screen2); |
break; |
} |
case 24: |
{ |
gui_ksys_put_image_window(img,x,y,countx,county); |
break; |
} |
} |
break; |
} |
default: break; |
} |
break; |
} |
case DRAW_OUTPUT_BUFFER: |
{ |
switch(screen.bits_per_pixel) |
{ |
case 24: |
{//check source image resolution |
switch(bits_per_pixel) |
{ |
case 32://display 32 bit image in 24 bit mode |
{//convert and draw 32 bit image in 24 bit buffer |
ptr_screen=screen.buffer+(screen.size_x*y+x)*3; |
add_screen=(screen.size_x-countx)*3; |
ptr_src=img; |
//copy line of byte with size x |
for(i=0;i<county;i++) |
{ |
for(j=0;j<countx;j++) |
{ |
*(char*)ptr_screen=*(char*)ptr_src; |
*((char*)ptr_screen+1)=*((char*)ptr_src+1); |
*((char*)ptr_screen+2)=*((char*)ptr_src+2); |
ptr_src+=4; |
ptr_screen+=3; |
} |
ptr_screen+=add_screen; |
} |
break; |
} |
case 24: |
{//display 24 bit image in 24 bit buffer |
ptr_screen=screen.buffer+(screen.size_x*y+x)*3; |
add_screen=screen.size_x*3; |
add_src=countx*3; |
//copy line of byte with size x |
for(i=0;i<county;i++) |
{ |
memmove(ptr_screen,img,add_src); |
ptr_screen+=add_screen; |
img+=add_src; |
} |
break; |
} |
default: break; |
} |
break; |
} |
case 32: |
{ //check source image resolution |
switch(bits_per_pixel) |
{ |
case 32: |
{//display 32 bit image in 32 bit mode |
ptr_screen=screen.buffer+(screen.size_x*y+x)*4; |
add_screen=screen.size_x*4; |
add_src=countx*4; |
//copy line of byte with size x |
for(i=0;i<county;i++) |
{ |
memmove(ptr_screen,img,add_src); |
ptr_screen+=add_screen; |
img+=add_src; |
} |
break; |
} |
case 24://display 24 bit image in 32 bit mode |
{ |
ptr_screen=screen.buffer+(screen.size_x*y+x)*4; |
add_screen=(screen.size_x-countx)*4; |
ptr_src=img; |
//copy line of byte with size x |
for(i=0;i<county;i++) |
{ |
for(j=0;j<countx;j++) |
{ |
*(char*)ptr_screen=*(char*)ptr_src; |
*((char*)ptr_screen+1)=*((char*)ptr_src+1); |
*((char*)ptr_screen+2)=*((char*)ptr_src+2); |
ptr_src+=3; |
ptr_screen+=4; |
} |
ptr_screen+=add_screen; |
} |
break; |
} |
default: break; |
} |
default: break; |
} |
} |
} |
} |
} |
//--------------------------------------------------------------------------------- |
// libGUI function drawing image on screen with finition |
//--------------------------------------------------------------------------------- |
void DrawImageFinit(finition_t *fin,int x,int y,int sizex,int sizey,char bits_per_pixel,char *img) |
{ |
int x1,y1,x2,y2,sx,sy; |
int xmin,xmax,ymin,ymax; |
int countline,countx,county,i,j; |
DWORD pitch_src,add_src; |
char *ptr_dest,*ptr_src; |
char bytes_per_pixel; |
char *buf; |
xmin=fin->x; |
xmax=fin->x+fin->sizex-1; |
ymin=fin->y; |
ymax=fin->y+fin->sizey-1; |
x1=x; |
y1=y; |
x2=x1+sizex-1; |
y2=y1+sizey-1; |
if (x2<xmin) return; |
if (x1>xmax) return; |
if (y2<ymin) return; |
if (y1>ymax) return; |
if (x1>=xmin && x2<=xmax && y1>=ymin && y2<=ymax) |
{ |
DrawImage(x,y,sizex,sizey,bits_per_pixel,img); |
return; |
} |
//finit x coordinates and sizex |
sx=x1-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x1=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y1-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y1=ymin; |
if (y2>ymax) y2=ymax; |
} |
countx=x2-x1+1; |
county=y2-y1+1; |
//cut finited rectangle from image and move them into buffer |
bytes_per_pixel=bits_per_pixel >> 3; |
buf=malloc(countx*county*bytes_per_pixel); |
ptr_dest=buf; |
pitch_src=sizex*bytes_per_pixel; |
ptr_src=img+pitch_src*(y1-y)+(x1-x)*bytes_per_pixel; |
add_src=sizex*bytes_per_pixel; |
countline=countx*bytes_per_pixel; |
switch(bits_per_pixel) |
{ |
case 32: |
case 24: |
case 16: |
case 8: |
{ |
for(i=0;i<county;i++) |
{ |
memmove(ptr_dest,ptr_src,countline); |
ptr_src+=add_src; |
ptr_dest+=countline; |
} |
break; |
} |
default: break; |
} |
//draw cutted by finition image |
DrawImage(x1,y1,countx,county,bits_per_pixel,buf); |
free(buf); |
} |
//--------------------------------------------------------------------------------- |
// libGUI function draw |
//--------------------------------------------------------------------------------- |
void Draw(struct FINITION *finition,int tool_name,...) |
{ |
va_list arguments; |
char *img; |
char first,second,bits_per_pixel; |
int xmin,xmax,ymin,ymax; |
int radius; |
int x,y,x2,y2,x_i,y_i; |
int sizex,sizey,sx,sy; |
float x_l1,y_l1,x_l2,y_l2,k,b; |
DWORD color,color_from,color_to; |
arguments=(va_list)&tool_name+sizeof(int); |
xmin=finition->x; |
xmax=finition->x+finition->sizex-1; |
ymin=finition->y; |
ymax=finition->y+finition->sizey-1; |
switch(tool_name) |
{ |
//tool Pixel |
case TOOL_PIXEL: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
if (x>=finition->x && x<=finition->x+finition->sizex |
&& y>=finition->y && y<=finition->y+finition->sizey) |
{ //pixel inside finition arrea |
DrawPixel(x,y,color); |
} |
} |
else |
{ //no finition |
DrawPixel(x,y,color); |
} |
break; |
} |
//tool Line |
case TOOL_LINE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
x2=va_arg(arguments,int); |
y2=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
sizex=abs(x2-x); |
sizey=abs(y2-y); |
if (CheckCrossRectangles(finition->x,finition->y,finition->sizex, |
finition->sizey,x,y,sizex,sizey)==FALSE) break; |
if (x>=finition->x && x<=finition->x+finition->sizex && |
y>=finition->y && y<=finition->y+finition->sizey && |
x2>=finition->x && x2<=finition->x+finition->sizex && |
y2>=finition->y && y2<=finition->y+finition->sizey) |
{ |
//line inside finition arrea |
DrawLine(x,y,x2,y2,color); |
break; |
} |
if (x==x2) break; |
//find coefficients of line |
x_l1=x; |
y_l1=y; |
x_l2=x2; |
y_l2=y2; |
k=(y_l1-y_l2)/(x_l1-x_l2); |
b=(y_l2*x_l1-y_l1*x_l2)/(x_l1-x_l2); |
sx=x2-x;//vectore x |
sy=y2-y;//vectore y |
if (x>=finition->x && x<=finition->x+finition->sizex && |
y>=finition->y && y<=finition->y+finition->sizey) |
{ //point x,y inside finition arrea |
//check cross with left vertical line of finition |
y_l1=k*finition->x+b; |
y_i=(int)y_l1; |
if (y_i>=finition->y && y_i<=finition->y+finition->sizey && sx<0) |
{ //first point for finited line |
x2=finition->x; |
y2=y_i; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
//check cross with up horizontal line of finition |
x_l1=(finition->y-b)/k; |
x_i=(int)x_l1; |
if (x_i>=finition->x && x_i<=finition->x+finition->sizex && sy<0) |
{ |
x2=x_i; |
y2=finition->y; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
//check cross with right vertical line of finition |
y_l1=k*(finition->x+finition->sizex)+b; |
y_i=(int)y_l1; |
if (y_i>=finition->y && y_i<=finition->y+finition->sizey && sx>0) |
{ |
x2=finition->x+finition->sizex; |
y2=y_i; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
//check cross with down horizontal line of finition |
x_l1=((finition->y+finition->sizey)-b)/k; |
x_i=(int)x_l1; |
if (x_i>=finition->x && x_i<=finition->x+finition->sizex && sy>0) |
{ |
x2=x_i; |
y2=finition->y+finition->sizey; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
} |
if (x2>=finition->x && x2<=finition->x+finition->sizex && |
y2>=finition->y && y2<=finition->y+finition->sizey) |
{ //point x,y inside finition arrea |
//check cross with left vertical line of finition |
y_l1=k*finition->x+b; |
y_i=(int)y_l1; |
if (y_i>=finition->y && y_i<=finition->y+finition->sizey && sx>0) |
{ //first point for finited line |
x=finition->x; |
y=y_i; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
//check cross with up horizontal line of finition |
x_l1=(finition->y-b)/k; |
x_i=(int)x_l1; |
if (x_i>=finition->x && x_i<=finition->x+finition->sizex && sy>0) |
{ |
x=x_i; |
y=finition->y; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
//check cross with right vertical line of finition |
y_l1=k*(finition->x+finition->sizex)+b; |
y_i=(int)y_l1; |
if (y_i>=finition->y && y_i<=finition->y+finition->sizey && sx<0) |
{ |
x=finition->x+finition->sizex; |
y=y_i; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
//check cross with down horizontal line of finition |
x_l1=((finition->y+finition->sizey)-b)/k; |
x_i=(int)x_l1; |
if (x_i>=finition->x && x_i<=finition->x+finition->sizex && sy<0) |
{ |
x=x_i; |
y=finition->y+finition->sizey; |
DrawLine(x,y,x2,y2,color); |
break; |
} |
} |
first=FALSE; |
second=FALSE; |
//check cross with left vertical line of finition |
y_l1=k*finition->x+b; |
y_i=(int)y_l1; |
if (y_i>=finition->y && y_i<=finition->y+finition->sizey) |
{ //first point for finited line |
x=finition->x; |
y=y_i; |
first=TRUE; |
} |
//check cross with up horizontal line of finition |
x_l1=(finition->y-b)/k; |
x_i=(int)x_l1; |
if (x_i>=finition->x && x_i<=finition->x+finition->sizex) |
{ |
if (first==FALSE) |
{ |
x=x_i; |
y=finition->y; |
} |
else |
{ |
x2=x_i; |
y2=finition->y; |
second=TRUE; |
} |
} |
//check cross with right vertical line of finition |
y_l1=k*(finition->x+finition->sizex)+b; |
y_i=(int)y_l1; |
if (y_i>=finition->y && y_i<=finition->y+finition->sizey) |
{ |
if (first==FALSE) |
{ |
x=finition->x+finition->sizex; |
y=y_i; |
} |
else |
{ |
x2=finition->x+finition->sizex; |
y2=y_i; |
second=TRUE; |
} |
} |
//check cross with down horizontal line of finition |
x_l1=((finition->y+finition->sizey)-b)/k; |
x_i=(int)x_l1; |
if (x_i>=finition->x && x_i<=finition->x+finition->sizex) |
{ |
if (first==FALSE) |
{ |
x=x_i; |
y=finition->y+finition->sizey; |
} |
else |
{ |
x2=x_i; |
y2=finition->y+finition->sizey; |
second=TRUE; |
} |
} |
if (first==TRUE && second==TRUE) |
{ |
//draw finited line |
DrawLine(x,y,x2,y2,color); |
} |
break; |
} |
else |
{ //no finition |
DrawLine(x,y,x2,y2,color); |
} |
break; |
} |
//tool VerticalLine |
case TOOL_VERTICAL_LINE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
y2=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
DrawVerticalLineFinit(finition,x,y,y2,color); |
} |
else |
{ |
DrawVerticalLine(x,y,y2,color); |
} |
break; |
} |
//tool HorizontalLine |
case TOOL_HORIZONTAL_LINE: |
{ |
x=va_arg(arguments,int); |
x2=va_arg(arguments,int); |
y=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
DrawHorizontalLineFinit(finition,x,x2,y,color); |
} |
else |
{ |
DrawHorizontalLine(x,x2,y,color); |
} |
break; |
} |
//tool Rectangle |
case TOOL_RECTANGLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (x2<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y>ymax) return; |
DrawRectangleFinit(finition,x,y,sizex,sizey,color); |
} |
else |
{ |
DrawRectangle(x,y,sizex,sizey,color); |
} |
break; |
} |
//tool FilledRectangle |
case TOOL_FILLED_RECTANGLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (x2<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y>ymax) return; |
//finit x coordinates and sizex |
sx=x-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y=ymin; |
if (y2>ymax) y2=ymax; |
} |
sizex=x2-x+1; |
sizey=y2-y+1; |
DrawFilledRectangle(x,y,sizex,sizey,color); |
} |
else |
{ |
DrawFilledRectangle(x,y,sizex,sizey,color); |
} |
break; |
} |
//tool GradientUpFilledRectangle |
case TOOL_GRADIENT_UP_FILLED_RECTANGLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color_from=va_arg(arguments,DWORD); |
color_to=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (x2<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y>ymax) return; |
//finit x coordinates and sizex |
sx=x-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y=ymin; |
if (y2>ymax) y2=ymax; |
} |
sizex=x2-x+1; |
sizey=y2-y+1; |
DrawGradientUpDownFilledRectangle(TRUE,x,y,sizex,sizey,color_from,color_to); |
} |
else |
{ |
DrawGradientUpDownFilledRectangle(TRUE,x,y,sizex,sizey,color_from,color_to); |
} |
break; |
} |
//tool GradientDownFilledRectangle |
case TOOL_GRADIENT_DOWN_FILLED_RECTANGLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color_from=va_arg(arguments,DWORD); |
color_to=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (x2<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y>ymax) return; |
//finit x coordinates and sizex |
sx=x-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y=ymin; |
if (y2>ymax) y2=ymax; |
} |
sizex=x2-x+1; |
sizey=y2-y+1; |
DrawGradientUpDownFilledRectangle(FALSE,x,y,sizex,sizey,color_from,color_to); |
} |
else |
{ |
DrawGradientUpDownFilledRectangle(FALSE,x,y,sizex,sizey,color_from,color_to); |
} |
break; |
} |
//tool GradientLeftFilledRectangle |
case TOOL_GRADIENT_LEFT_FILLED_RECTANGLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color_from=va_arg(arguments,DWORD); |
color_to=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (x2<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y>ymax) return; |
//finit x coordinates and sizex |
sx=x-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y=ymin; |
if (y2>ymax) y2=ymax; |
} |
sizex=x2-x+1; |
sizey=y2-y+1; |
DrawGradientLeftRightFilledRectangle(TRUE,x,y,sizex,sizey,color_from,color_to); |
} |
else |
{ |
DrawGradientLeftRightFilledRectangle(TRUE,x,y,sizex,sizey,color_from,color_to); |
} |
break; |
} |
//tool GradientRightFilledRectangle |
case TOOL_GRADIENT_RIGHT_FILLED_RECTANGLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color_from=va_arg(arguments,DWORD); |
color_to=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
x2=x+sizex-1; |
y2=y+sizey-1; |
if (x2<xmin) return; |
if (x>xmax) return; |
if (y2<ymin) return; |
if (y>ymax) return; |
//finit x coordinates and sizex |
sx=x-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y=ymin; |
if (y2>ymax) y2=ymax; |
} |
sizex=x2-x+1; |
sizey=y2-y+1; |
DrawGradientLeftRightFilledRectangle(FALSE,x,y,sizex,sizey,color_from,color_to); |
} |
else |
{ |
DrawGradientLeftRightFilledRectangle(FALSE,x,y,sizex,sizey,color_from,color_to); |
} |
break; |
} |
//tool Circle |
case TOOL_CIRCLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
radius=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
DrawCircleFinit(finition,x,y,radius,color); |
} |
else |
{ |
DrawCircle(x,y,radius,color); |
} |
break; |
} |
//tool FilledCircle |
case TOOL_FILLED_CIRCLE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
radius=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
DrawFilledCircleFinit(finition,x,y,radius,color); |
} |
else |
{ |
DrawFilledCircle(x,y,radius,color); |
} |
break; |
} |
//tool Ellipse |
case TOOL_ELLIPSE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
DrawEllipseFinit(finition,x,y,sizex,sizey,color); |
} |
else |
{ |
DrawEllipse(x,y,sizex,sizey,color); |
} |
break; |
} |
//tool FilledEllipse |
case TOOL_FILLED_ELLIPSE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
color=va_arg(arguments,DWORD); |
if (finition->flags & FINITION_ON) |
{ |
DrawFilledEllipseFinit(finition,x,y,sizex,sizey,color); |
} |
else |
{ |
DrawFilledEllipse(x,y,sizex,sizey,color); |
} |
break; |
} |
//tool Image |
case TOOL_IMAGE: |
{ |
x=va_arg(arguments,int); |
y=va_arg(arguments,int); |
sizex=va_arg(arguments,int); |
sizey=va_arg(arguments,int); |
bits_per_pixel=(char)va_arg(arguments,int); |
img=va_arg(arguments,char*); |
if (finition->flags & FINITION_ON) |
{ |
DrawImageFinit(finition,x,y,sizex,sizey,bits_per_pixel,img); |
} |
else |
{ |
DrawImage(x,y,sizex,sizey,bits_per_pixel,img); |
} |
break; |
} |
} |
va_end(arguments); |
} |
/programs/develop/libraries/libGUI/SRC/fonts_meneger.h |
---|
0,0 → 1,63 |
/* |
font meneger header structure |
*/ |
#define FONT_FLAG_DEFAULT_FONT_ON 0x1 |
#define FONT_FLAG_DEFAULT_FONT_OFF 0xfe |
#define FONT_FLAG_DRAW_BACKGROUND_ON 0x2 |
#define FONT_FLAG_DRAW_BACKGROUND_OFF 0xfd |
#define FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_ON 0x4 |
#define FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_OFF 0xfb |
#define FONT_CONSTANT_SIZE -1 |
//some types encoding characters |
#define FONT_TYPE_ASCII 0x1 |
#define FONT_TYPE_UNICODE 0x2 |
/////////////////////////////////////////////////////////// |
// some ASCII encodings |
/////////////////////////////////////////////////////////// |
//cyrillic encodings |
#define FONT_ENCODING_CYRILLIC_IBM866 0x1 |
#define FONT_ENCODING_CYRILLIC_IBM437 0x2 |
#define FONT_ENCODING_CYRILLIC_KOI8R 0x4 |
#define FONT_ENCODING_CYRILLIC_ISO8859_5 0x8 |
#define FONT_ENCODING_CYRILLIC_CP1251 0x10 |
#pragma pack(push,1) |
static struct |
{ |
DWORD *fnt_fd; |
DWORD *fnt_bk; |
DWORD *default_font; |
DWORD number_fonts; |
}FontsMeneger; |
#pragma pack(pop) |
#pragma pack(push,1) |
struct FONT |
{ |
DWORD *fnt_draw; |
DWORD *fnt_unpacker; |
DWORD *fnt_fd; |
DWORD *fnt_bk; |
int sizex; |
int sizey; |
int size; |
int encoding_type; |
char *font; |
char *fnt_name; |
DWORD type; |
DWORD flags; |
}; |
#pragma pack(pop) |
typedef struct FONT font_t; |
static char *default_fonts_path="/sys/fonts/"; |
void (*DrawFont)(finition_t *fin,int fx,int fy,DWORD color,DWORD background_color,font_t *font,BYTE *s); |
/programs/develop/libraries/libGUI/SRC/fonts_meneger.inc |
---|
0,0 → 1,373 |
/* |
menegement of fonts |
*/ |
//--------------------------------------------------------------------------------- |
// destroy font |
//--------------------------------------------------------------------------------- |
void DestroyFont(font_t *font) |
{ |
font_t *seek_font; |
font_t *exchange_font; |
font_t *last_font; |
font_t *next_font; |
if (font==(font_t*)NULL) return; |
if (FontsMeneger.fnt_bk==FontsMeneger.fnt_fd) |
{ |
//parent have got alone font |
if (FontsMeneger.fnt_bk==(DWORD*)font) |
{ |
#ifdef DEBUG |
printf("\ndestroyed font %d font name=%s",(int)font,(char*)font->fnt_name); |
#endif |
free(font); |
FontsMeneger.fnt_bk=(DWORD*)NULL; |
FontsMeneger.fnt_fd=(DWORD*)NULL; |
} |
return; |
} |
seek_font=(font_t*)FontsMeneger.fnt_bk; |
while(seek_font!=(font_t*)NULL) |
{ |
if (seek_font==font) |
{ |
//delete font from fonts's cash |
last_font=(font_t*)seek_font->fnt_bk; |
next_font=(font_t*)seek_font->fnt_fd; |
if ((last_font!=(font_t*)NULL) && (next_font!=(font_t*)NULL)) |
{//deliting font isn't first font and isn't endest |
next_font->fnt_bk=(DWORD*)last_font; |
last_font->fnt_fd=(DWORD*)next_font; |
} |
else |
{ |
if (last_font==(font_t*)NULL) |
{//deliting font is first font of Parend |
FontsMeneger.fnt_bk=(DWORD*)next_font; |
next_font->fnt_bk=(DWORD*)NULL; |
if (next_font->fnt_fd==(DWORD*)NULL) |
{ |
FontsMeneger.fnt_fd=(DWORD*)next_font; |
FontsMeneger.fnt_bk=(DWORD*)next_font; |
} |
} |
if (next_font==(font_t*)NULL) |
{ |
//there isn't next fonts |
last_font->fnt_fd=(DWORD*)NULL; |
FontsMeneger.fnt_fd=(DWORD*)last_font; |
} |
} |
#ifdef DEBUG |
printf("\ndestroyed font %d font name=%s",(int)font,(char*)font->fnt_name); |
#endif |
free(font); |
break; |
} |
exchange_font=(font_t*)seek_font->fnt_fd; |
seek_font=exchange_font; |
} |
} |
void *CreateFont(void) |
{ |
font_t *font; |
font_t *backward_font; |
font=malloc(sizeof(struct FONT)); |
if (FontsMeneger.fnt_bk==(DWORD*)NULL) |
{//not yet fonts |
FontsMeneger.fnt_bk=(DWORD*)font; |
FontsMeneger.fnt_fd=(DWORD*)font; |
font->fnt_bk=(DWORD*)NULL; |
font->fnt_fd=(DWORD*)NULL; |
} |
else |
{ |
backward_font=(font_t*)FontsMeneger.fnt_fd; |
FontsMeneger.fnt_fd=(DWORD*)font; |
backward_font->fnt_fd=(DWORD*)font; |
font->fnt_bk=(DWORD*)backward_font; |
font->fnt_fd=(DWORD*)NULL; |
} |
return(font); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// CHAR.MT and CHAR2.MT fonts unpacker |
//////////////////////////////////////////////////////////////////////////////// |
void CHAR_MT_FontsUnpacker(unsigned char *loaded_font,font_t *font,char font_type) |
{ |
int i,j,k; |
unsigned char c; |
unsigned char *p; |
if (font_type==FALSE) |
{//CHAR.MT |
font->font=malloc(6*9*256); |
p=(unsigned char*)font->font; |
for(j=0;j<256;j++) |
{ |
for(i=0;i<9;i++) |
{ |
c=(unsigned char)(*loaded_font); |
p[5]=(unsigned char)(c & 0x20); |
p[4]=(unsigned char)(c & 0x10); |
p[3]=(unsigned char)(c & 0x8); |
p[2]=(unsigned char)(c & 0x4); |
p[1]=(unsigned char)(c & 0x2); |
p[0]=(unsigned char)(c & 0x1); |
p+=6; |
loaded_font++; |
} |
} |
font->sizex=6; |
font->sizey=9; |
} |
else |
{//CHAR2.MT |
font->font=malloc(8*10*256); |
p=(unsigned char*)font->font; |
for(j=0;j<256;j++) |
{ |
for(i=0;i<10;i++) |
{ |
c=(unsigned char)(*loaded_font); |
p[7]=(unsigned char)(c & 0x80); |
p[6]=(unsigned char)(c & 0x40); |
p[5]=(unsigned char)(c & 0x20); |
p[4]=(unsigned char)(c & 0x10); |
p[3]=(unsigned char)(c & 0x8); |
p[2]=(unsigned char)(c & 0x4); |
p[1]=(unsigned char)(c & 0x2); |
p[0]=(unsigned char)(c & 0x1); |
p+=8; |
loaded_font++; |
} |
} |
font->sizex=8; |
font->sizey=10; |
} |
font->size=FONT_CONSTANT_SIZE; |
font->type=FONT_TYPE_ASCII; |
font->encoding_type=FONT_ENCODING_CYRILLIC_IBM866; |
} |
//////////////////////////////////////////////////////////////////////////////// |
// CHAR.MT and CHAR2.MT fonts draw |
//////////////////////////////////////////////////////////////////////////////// |
void MonofontDraw(finition_t *fin,int fx,int fy, |
DWORD color,DWORD background_color, |
font_t *font,unsigned char *s) |
{ |
unsigned int i,j,k,step,len; |
int x,y,size_x,save_size_x,save_size_y; |
unsigned char *p,*buf,*save_buf; |
unsigned char c; |
DWORD draw_output; |
step=font->sizex*font->sizey; |
len=strlen(s); |
if (font->flags & FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_ON) |
{ |
if (font->flags & FONT_FLAG_DRAW_BACKGROUND_ON) |
{//there is a fon and not finition for draw |
//alocate a buffer for draw text |
size_x=font->sizex*len; |
c=screen.bits_per_pixel >> 3; |
i=step*c*len; |
buf=malloc(i); |
//save current screen parameters |
save_buf=screen.buffer; |
save_size_x=screen.size_x; |
save_size_y=screen.size_y; |
draw_output=screen.draw_output; |
//load parameters of local buffer |
screen.buffer=buf; |
screen.size_x=size_x; |
screen.size_y=font->sizey; |
screen.draw_output=DRAW_OUTPUT_BUFFER; |
//fill buffer by background color |
FillArrea(buf,i,screen.bits_per_pixel,background_color); |
//draw text |
x=0; |
for(k=0;k<len;k++) |
{ |
c=s[k]; |
p=font->font+step*c; |
for(j=0;j<font->sizey;j++) |
{ |
for(i=0;i<font->sizex;i++) |
{ |
if (*p) DrawPixel(x+i,j,color); |
p++; |
} |
} |
x=x+font->sizex; |
} |
//restore screen parameters |
screen.buffer=save_buf; |
screen.size_x=save_size_x; |
screen.size_y=save_size_y; |
screen.draw_output=draw_output; |
//move text from local buffer to screen |
if (fin->flags & FINITION_ON) |
DrawImageFinit(fin,fx,fy,size_x,font->sizey,screen.bits_per_pixel,buf); |
else |
DrawImage(fx,fy,size_x,font->sizey,screen.bits_per_pixel,buf); |
//free local buffer |
free(buf); |
} |
else |
{ |
if (fin->flags & FINITION_ON) |
{//not background and finition for draw |
x=fx; |
y=fy; |
for(k=0;k<len;k++) |
{ |
c=s[k]; |
p=font->font+step*c; |
for(j=0;j<font->sizey;j++) |
{ |
for(i=0;i<font->sizex;i++) |
{ |
if (*p) DrawPixelFinit(fin,x+i,y+j,color); |
p++; |
} |
} |
x=x+font->sizex; |
} |
} |
else |
{//not background and not finition for draw |
x=fx; |
y=fy; |
for(k=0;k<len;k++) |
{ |
c=s[k]; |
p=font->font+step*c; |
for(j=0;j<font->sizey;j++) |
{ |
for(i=0;i<font->sizex;i++) |
{ |
if (*p) DrawPixel(x+i,y+j,color); |
p++; |
} |
} |
x=x+font->sizex; |
} |
} |
} |
} |
} |
//////////////////////////////////////////////////////////////////////////////// |
// fonts loader |
//////////////////////////////////////////////////////////////////////////////// |
font_t *LoadFont(char *fullfontname) |
{ |
char *path; |
char *c; |
BYTE *buf; |
long filesize; |
int len1,len2,i; |
font_t *font; |
static DWORD buf_for_size[2]; |
static DWORD buf_for_pos[2]; |
path=malloc(263); |
if (strchr(fullfontname,'/')==NULL) |
{ |
len1=strlen(default_fonts_path); |
len2=strlen(fullfontname); |
memmove(path,default_fonts_path,len1); |
memmove(path+len1,fullfontname,len2); |
*(path+len1+len2)='\0'; |
} |
else |
memmove(path,fullfontname,strlen(fullfontname)); |
if (gui_get_file_size(path,buf_for_size)==KOLIBRIOS_SYS_FILE_ACCESS_SUCCESSFULLY) |
{ |
filesize=buf_for_size[0]; |
buf=malloc(filesize); |
//load fonts in buffer |
gui_read_file(path,buf_for_pos,filesize,buf); |
free(path); |
//register font |
font=CreateFont(); |
c=strrchr(fullfontname,'/'); |
if(c==NULL) font->fnt_name=fullfontname; |
else |
font->fnt_name=(char*)(c+1); |
//check font type |
c=strstr(font->fnt_name,"CHAR.MT");//check standart type of fonts |
if (c!=NULL) |
{ |
font->fnt_unpacker=(DWORD*)&CHAR_MT_FontsUnpacker; |
font->fnt_draw=(DWORD*)&MonofontDraw; |
CHAR_MT_FontsUnpacker(buf,font,FALSE);//CHAR.MT |
free(buf); |
font->flags=0; |
font->flags|=FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_ON; |
} |
c=strstr(font->fnt_name,"CHAR2.MT");//check standart type of fonts |
if (c!=NULL) |
{ |
font->fnt_unpacker=(DWORD*)&CHAR_MT_FontsUnpacker; |
font->fnt_draw=(DWORD*)&MonofontDraw; |
CHAR_MT_FontsUnpacker(buf,font,TRUE);//CHAR2.MT |
free(buf); |
font->flags=0; |
font->flags|=FONT_FLAG_ORIENTATION_HORIZONTAL_FROM_LEFT_TO_RIGHT_ON; |
} |
//not other fonts yet |
} |
else |
{ |
#ifdef DEBUG |
printf("\ncannot load font %s",path); |
#endif |
free(path); |
return(NULL); |
} |
FontsMeneger.number_fonts++; |
return(font); |
} |
void FreeFont(font_t *font) |
{ |
if (font==(font_t*)FontsMeneger.default_font) return; |
free(font->font); |
DestroyFont(font); |
} |
/programs/develop/libraries/libGUI/SRC/keys.h |
---|
0,0 → 1,8 |
/* |
scan codes of keys |
*/ |
//Scan Codes of some keys in pressed state |
#define SC_TAB 15 |
#define SC_ENTER 28 |
#define SC_SPACE 57 |
/programs/develop/libraries/libGUI/SRC/kolibri_system.h |
---|
0,0 → 1,658 |
/* |
some system function of KolibriOS |
*/ |
#define KOLIBRIOS_SYS_EVENT_REDRAW 1 |
#define KOLIBRIOS_SYS_EVENT_KEYS 2 |
#define KOLIBRIOS_SYS_EVENT_BUTTON_PRESSED 3 |
#define KOLIBRIOS_SYS_EVENT_REDRAW_BACKGROUND 5 |
#define KOLIBRIOS_SYS_EVENT_MOUSE 6 |
#define KOLIBRIOS_SYS_EVENT_IPC 7 |
#define KOLIBRIOS_SYS_EVENT_NET 8 |
#define KOLIBRIOS_SYS_EVENT_DEBUG 9 |
#define KOLIBRIOS_SYS_MOUSE_BUTTON_LEFT_DOWN 0x1 |
#define KOLIBRIOS_SYS_MOUSE_BUTTON_RIGHT_DOWN (0x1<<1) |
#define KOLIBRIOS_SYS_MOUSE_BUTTON_MIDDLE_DOWN (0x1 <<2) |
#define KOLIBRIOS_SYS_MOUSE_BUTTON_4_DOWN (0x1 <<3) |
#define KOLIBRIOS_SYS_MOUSE_BUTTON_5_DOWN (0x1 <<4) |
#define KOLIBRIOS_SYS_FILE_ACCESS_SUCCESSFULLY 0 |
#define KOLIBRIOS_SYS_FILE_UNDEFINED_PARTITION_OR_HARDDRIVE_BASE 1 |
#define KOLIBRIOS_SYS_FILE_FUNCTION_DONT_SUPPOROTE_FOR_CURRENT_FILE_SYSTEM 2 |
#define KOLIBRIOS_SYS_FILE_UNKNOWN_FILE_SYSTEM 3 |
#define KOLIBRIOS_SYS_FILE_NOT_FOUND 5 |
#define KOLIBRIOS_SYS_FILE_FINISHED 6 |
#define KOLIBRIOS_SYS_FILE_POINTER_OUTOFMEMORY_APPLICATION 7 |
#define KOLIBRIOS_SYS_FILE_MEMORY_OF_DEVICE_FILLED 8 |
#define KOLIBRIOS_SYS_FILE_TABLE_DESTROYED 9 |
#define KOLIBRIOS_SYS_FILE_ACCESS_DENITED 10 |
#define KOLIBRIOS_SYS_FILE_DEVICE_ERROR 11 |
#pragma pack(push,1) |
struct KOLIBRIOS_FILEIO |
{ |
DWORD number_subfunction; |
DWORD offset_in_file_low; |
DWORD offset_in_file_hight; |
DWORD size; |
DWORD *data; |
BYTE null; |
char *full_file_path; |
}; |
#pragma pack(pop) |
typedef struct KOLIBRIOS_FILEIO fileio_t; |
#pragma pack(push,1) |
struct BLOCK_DATA_ENTRY_DIRECTORY |
{ |
DWORD attributes; |
DWORD types_data_of_name; |
DWORD time_created_file; |
DWORD date_created_file; |
DWORD time_last_access; |
DWORD date_last_access; |
DWORD time_last_modification; |
DWORD date_last_modification; |
DWORD file_size_low; |
DWORD file_size_hight; |
DWORD *filename; |
}; |
#pragma pack(pop) |
typedef struct BLOCK_DATA_ENTRY_DIRECTORY bded_t; |
#pragma pack(push,1) |
struct PROCESS_TABLE |
{ |
int cpu_usage; //+0 |
int window_pos_info; //+4 |
short int reserved1; //+8 |
char name[12]; //+10 |
int memstart; //+22 |
int memused; //+26 |
int pid; //+30 |
int winx_start; //+34 |
int winy_start; //+38 |
int winx_size; //+42 |
int winy_size; //+46 |
short int slot_info; //+50 |
short int reserved2; //+52 |
int clientx; //+54 |
int clienty; //+58 |
int clientwidth; //+62 |
int clientheight; //+66 |
unsigned char window_state; //+70 |
char reserved3[1024-71]; //+71 |
}; |
#pragma pack(pop) |
typedef struct PROCESS_TABLE process_table_t; |
#pragma pack(push,1) |
struct IMPORT |
{ |
char *name; |
void *data; |
}; |
#pragma pack(pop) |
typedef struct IMPORT import_t; |
static DWORD gui_get_file_size(char *filename,DWORD *buf_for_size); |
static DWORD gui_read_file(char *filename,DWORD *buf_pos_size,DWORD size_read,char *buf); |
static DWORD gui_create_rewrite_file(char *filename,DWORD *buf_pos_size,DWORD size_write,char *buf); |
static DWORD gui_append_to_file(char *filename,DWORD *buf_pos_size,DWORD size_write,char *buf); |
static void gui_debug_out_str(char *s); |
static void* gui_cofflib_getproc(import_t *lib, char *name); |
#define alwinline __attribute__((always_inline)) |
//------------------------------------------------------------------------------------------ |
// draw window |
//------------------------------------------------------------------------------------------ |
extern inline void __attribute__((always_inline)) gui_ksys_draw_window(DWORD x,DWORD y,DWORD sizex,DWORD sizey,DWORD flags) |
{ |
__asm__ __volatile__( |
"xorl %%eax,%%eax\n\t" |
"movl %0,%%ebx\n\t" |
"movl %1,%%ecx\n\t" |
"movl %4,%%edx\n\t" |
"shll $16,%%ebx\n\t" |
"shll $16,%%ecx\n\t" |
"addl %2,%%ebx\n\t" |
"addl %3,%%ecx\n\t" |
"int $0x40" |
:/*no output*/ |
:"g"(x),"g"(y),"g"(sizex),"g"(sizey),"g"(flags) |
:"eax","ebx","ecx","edx"); |
} |
//------------------------------------------------------------------------------------------ |
// begin redraw window |
//------------------------------------------------------------------------------------------ |
extern inline void __attribute__((always_inline)) gui_ksys_begin_draw_window(void) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(12),"b"(1)); |
} |
//------------------------------------------------------------------------------------------ |
// finish redraw window |
//------------------------------------------------------------------------------------------ |
extern inline void __attribute__((always_inline)) gui_ksys_finish_draw_window(void) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(12),"b"(2)); |
} |
//------------------------------------------------------------------------------------------ |
// set new position and new size of window |
//------------------------------------------------------------------------------------------ |
extern inline void alwinline gui_ksys_set_position_and_size_window(DWORD new_x, |
DWORD new_y,DWORD new_sizex,DWORD new_sizey) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(67),"b"(new_x),"c"(new_y),"d"(new_sizex),"S"(new_sizey)); |
} |
//------------------------------------------------------------------------------------------ |
// set title of window |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_set_title_window(char *title) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(71),"b"(1),"c"(title)); |
} |
//------------------------------------------------------------------------------------------ |
// delete title of window |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_delete_title_window(void) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(71),"b"(1),"c"(0)); |
} |
//------------------------------------------------------------------------------------------ |
// get information about current process |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_current_process_information(void *mem) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(9),"b"(mem),"c"(-1)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// delete title of window |
//------------------------------------------------------------------------------------------ |
extern inline int __attribute__((always_inline)) gui_ksys_get_skin_height(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(48),"b"(4)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get pressed key |
//------------------------------------------------------------------------------------------ |
extern inline int __attribute__((always_inline)) gui_ksys_get_key(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(2)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// set keyboard input mode |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_set_keyboard_input_mode(int mode) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(66),"b"(1),"c"(mode)); |
} |
//------------------------------------------------------------------------------------------ |
// get keyboard input mode |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_keyboard_input_mode(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(66),"b"(2)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get state of menegers keys |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_state_menegers_keys(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(66),"b"(3)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// set events mask |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_set_events_mask(DWORD mask) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(40),"b"(mask)); |
} |
//------------------------------------------------------------------------------------------ |
// wait event |
//------------------------------------------------------------------------------------------ |
extern inline int __attribute__((always_inline)) gui_ksys_wait_event(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(10)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// check for event |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_check_event(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(11)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// wait event while not timeout |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_wait_event_with_timeout(DWORD timeout) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(23),"b"(timeout)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get code of pressed button |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_code_pressed_button(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(17)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get window mouse coordinates |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_window_mouse_coordinates(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(37),"b"(1)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get screen mouse coordinates |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_screen_mouse_coordinates(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(37),"b"(0)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get mouse buttons state |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_mouse_buttons_state(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(37),"b"(2)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get mouse ruler state |
//------------------------------------------------------------------------------------------ |
extern inline int gui_ksys_get_mouse_ruler_state(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(37),"b"(7)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// put pixel in window |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_put_pixel_window(int x,int y,DWORD color) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(1),"b"(x),"c"(y),"d"(color)); |
} |
//------------------------------------------------------------------------------------------ |
// put image in window |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_put_image_window(char *p,int x,int y,int sizex,int sizey) |
{ |
__asm__ __volatile__( |
"shll $16,%%ecx\n\t" |
"shll $16,%%edx\n\t" |
"addl %%esi,%%ecx\n\t" |
"addl %%edi,%%edx\n\t" |
"int $0x40" |
:/*no output*/ |
:"a"(7),"b"(p),"c"(sizex),"d"(x),"S"(sizey),"D"(y)); |
} |
//------------------------------------------------------------------------------------------ |
// draw filled rectangle in window |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_draw_filled_rectangle_window(int x,int y,int sizex,int sizey,DWORD color) |
{ |
__asm__ __volatile__( |
"shll $16,%%ebx\n\t" |
"shll $16,%%ecx\n\t" |
"addl %%esi,%%ebx\n\t" |
"addl %%edi,%%ecx\n\t" |
"int $0x40" |
:/*no output*/ |
:"a"(13),"b"(x),"c"(y),"d"(color),"S"(sizex),"D"(sizey)); |
} |
//------------------------------------------------------------------------------------------ |
// get screen size |
//------------------------------------------------------------------------------------------ |
extern inline DWORD gui_ksys_get_screen_size(void) |
{ |
DWORD value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(14)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get color of pixel in coordinates (x,y) |
//------------------------------------------------------------------------------------------ |
extern inline DWORD gui_ksys_get_color_pixel_window(DWORD coordinates) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(35),"b"(coordinates)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// get bits per pixel on the screen |
//------------------------------------------------------------------------------------------ |
extern inline DWORD gui_ksys_get_screen_bits_per_pixel(void) |
{ |
int value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(61),"b"(2)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// draw line in window |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_draw_line_window(int x1,int y1,int x2,int y2,DWORD color) |
{ |
__asm__ __volatile__( |
"shll $16,%%ebx\n\t" |
"shll $16,%%ecx\n\t" |
"addl %%esi,%%ebx\n\t" |
"addl %%edi,%%ecx\n\t" |
"int $0x40" |
:/*no output*/ |
:"a"(38),"b"(x1),"c"(y1),"d"(color),"S"(x2),"D"(y2)); |
} |
//------------------------------------------------------------------------------------------ |
// get standart colors table |
//------------------------------------------------------------------------------------------ |
extern inline void gui_ksys_get_standart_colors_table(char *buf) |
{ |
__asm__ __volatile__( |
"int $0x40" |
:/*no output*/ |
:"a"(48),"b"(3),"c"(buf),"d"(40)); |
} |
//------------------------------------------------------------------------------------------ |
// get time from start system to current in 1/100 sec. |
//------------------------------------------------------------------------------------------ |
extern inline DWORD gui_ksys_get_ticks(void) |
{ |
DWORD value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(26),"b"(9)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// initialize heap of memory |
//------------------------------------------------------------------------------------------ |
extern inline DWORD gui_ksys_init_user_heap(void) |
{ |
DWORD value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(68),"b"(11)); |
return(value); |
} |
//------------------------------------------------------------------------------------------ |
// alloctae size bytes of user memory |
//------------------------------------------------------------------------------------------ |
extern inline void* gui_ksys_malloc(DWORD size) |
{ |
void *value; |
__asm__ __volatile__( |
+ :"=a"(value) |
+ :"a"(68),"b"(12),"c"(size) |
+ :"memory"); |
+ |
+ return(value); |
+} |
+ |
+//------------------------------------------------------------------------------------------ |
+// free pointer of memory |
+//------------------------------------------------------------------------------------------ |
+extern inline void gui_ksys_free(void *mem) |
+{ |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ : |
+ :"a"(68),"b"(13),"c"(mem) |
+ :"memory"); |
+} |
+ |
+//------------------------------------------------------------------------------------------ |
+// reallocate of memory |
+//------------------------------------------------------------------------------------------ |
+extern inline void* gui_ksys_realloc(DWORD new_size,void *old_mem) |
+{ |
+ void *new_mem; |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ :"=a"(new_mem) |
+ :"a"(68),"b"(20),"c"(new_size),"d"(old_mem) |
+ :"memory"); |
+ |
+ return(new_mem); |
+} |
+ |
+ |
+//------------------------------------------------------------------------------------------ |
+// load user mode DLL |
+//------------------------------------------------------------------------------------------ |
+extern inline void* gui_ksys_load_dll(char *path) |
+{ |
+ void *dll_export; |
+ |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ :"=a"(dll_export) |
+ :"a"(68),"b"(19),"c"(path)); |
+ |
+ return(dll_export); |
+} |
+ |
+//------------------------------------------------------------------------------------------ |
+// create thred |
+//------------------------------------------------------------------------------------------ |
+extern inline void* gui_ksys_create_thread(DWORD *thread_eip,DWORD *thread_esp) |
+{ |
+ void *thread_TID; |
+ |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ :"=a"(thread_TID) |
+ :"a"(51),"b"(1),"c"(thread_eip),"d"(thread_esp) |
+ :"memory"); |
+ |
+ return(thread_TID); |
+} |
+ |
+//------------------------------------------------------------------------------------------ |
+// acces to files input output |
+//------------------------------------------------------------------------------------------ |
+extern inline DWORD gui_ksys_files_io(fileio_t *f,DWORD value) |
+{ |
+ DWORD err_status; |
+ |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ :"=a"(err_status),"=b"(value) |
+ :"a"(70),"b"(f)); |
+ |
+ return(err_status); |
+} |
+ |
+//------------------------------------------------------------------------------------------ |
+// debug board output |
+//------------------------------------------------------------------------------------------ |
+extern inline void gui_ksys_debug_out(int c) |
+{ |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ : |
+ :"a"(63),"b"(1),"c"(c)); |
+} |
+ |
+//------------------------------------------------------------------------------------------ |
+// KolibriOS system exit program |
+//------------------------------------------------------------------------------------------ |
+extern inline void gui_ksys_exit(int value) |
+{ |
+ __asm__ __volatile__( |
+ "int $0x40" |
+ : |
+ :"a"(-1),"b"(value)); |
+} |
+ |
/programs/develop/libraries/libGUI/SRC/kolibri_system.inc |
---|
0,0 → 1,67 |
/* |
some system function of KolibriOS and founded of them functions |
*/ |
static DWORD gui_get_file_size(char *filename,DWORD *buf_for_size) |
{ |
static char buf[44]; |
static fileio_t f; |
bded_t *bded; |
DWORD status,value; |
f.number_subfunction=5; |
f.data=(DWORD*)buf; |
f.full_file_path=filename; |
status=gui_ksys_files_io(&f,value); |
if (status==KOLIBRIOS_SYS_FILE_ACCESS_SUCCESSFULLY) |
{ |
bded=(bded_t*)buf; |
*buf_for_size=bded->file_size_low; |
buf_for_size++; |
*buf_for_size=bded->file_size_hight; |
} |
return(status); |
} |
static DWORD gui_read_file(char *filename,DWORD *buf_pos_size,DWORD size_read,char *buf) |
{ |
static fileio_t f; |
DWORD status,value; |
f.number_subfunction=0; |
f.offset_in_file_low=(DWORD)*buf_pos_size;buf_pos_size++; |
f.offset_in_file_hight=(DWORD)*buf_pos_size; |
f.size=size_read; |
f.data=(DWORD*)buf; |
f.full_file_path=filename; |
status=gui_ksys_files_io(&f,value); |
return(status); |
} |
static void gui_debug_out_str(char *s) |
{ |
while(*s) |
{ |
if (*s=='\n') gui_ksys_debug_out(13); |
gui_ksys_debug_out(*s); |
s++; |
} |
} |
static void* gui_cofflib_getproc(import_t *lib, char *name) |
{ |
int i; |
for(i = 0; lib[i].name && strcmp(name, lib[i].name); i++); |
if(lib[i].name) return lib[i].data; |
else return NULL; |
} |
/programs/develop/libraries/libGUI/SRC/libGUI.c |
---|
0,0 → 1,168 |
/* |
libGUI dinamic library |
(c) andrew_programmer 2009 |
*/ |
//service libGUI types of data,functions and constants |
#include "types.h" |
#include "libGUI.h" |
#include "kolibri_system.h" |
#include "draw_controls.h" |
#include "fonts_meneger.h" |
#include "keys.h" |
//controls |
#include "control_button.h" |
#include "control_image.h" |
#include "control_progress_bar.h" |
#include "control_scroll_bar.h" |
#include "control_scrolled_window.h" |
#include "control_text.h" |
//some libC functions |
#include "stdarg.h" |
#include "stdio.h" |
#include "string.h" |
#include "stdlib.h" |
#include "stdio.inc" |
#include "string.inc" |
#include "malloc.inc" |
#include "stdlib.inc" |
#include "kolibri_system.inc" |
#include "draw_controls.inc" |
#include "fonts_meneger.inc" |
#include "libGUI_menegement.inc" |
#include "parent_window.inc" |
#include "main_libGUI.inc" |
#include "control_text.inc" |
#include "control_image.inc" |
#include "control_button.inc" |
#include "control_progress_bar.inc" |
#include "control_scroll_bar.inc" |
#include "control_scrolled_window.inc" |
typedef struct |
{ |
char *name; |
void *function; |
}export_t; |
//char szSTART[] = "START"; |
char szLibGUIversion[] = "LibGUIversion"; |
char szInitLibGUI[] = "InitLibGUI"; |
char szLibGUImain[] = "LibGUImain"; |
char szQuitLibGUI[] = "QuitLibGUI"; |
char szCreateWindow[] = "CreateWindow"; |
char szSetWindowSizeRequest[] = "SetWindowSizeRequest"; |
char szPackControls[] = "PackControls"; |
char szDestroyControl[] = "DestroyControl"; |
char szSetControlSizeRequest[] = "SetControlSizeRequest"; |
char szGetControlSizeX[] = "GetControlSizeX"; |
char szGetControlSizeY[] = "GetControlSizeY"; |
char szSetControlNewPosition[] = "SetControlNewPosition"; |
char szGetControlPositionX[] = "GetControlPositionX"; |
char szGetControlPositionY[] = "GetControlPositionY"; |
char szSetFocuse[] = "SetFocuse"; |
char szRedrawControl[] = "RedrawControl"; |
char szSpecialRedrawControl[] = "SpecialRedrawControl"; |
char szSetCallbackFunction[] = "SetCallbackFunction"; |
char szBlockCallbackFunction[] = "BlockCallbackFunction"; |
char szUnblockCallbackFunction[] = "UnblockCallbackFunction"; |
char szSetIDL_Function[] = "SetIDL_Function"; |
char szDestroyIDL_Function[] = "DestroyIDL_Function"; |
char szSetTimerCallbackForFunction[] = "SetTimerCallbackForFunction"; |
char szDestroyTimerCallbackForFunction[] = "DestroyTimerCallbackForFunction"; |
char szSetCallbackFunctionForEvent[] = "SetCallbackFunctionForEvent"; |
char szDestroyCallbackFunctionForEvent[] = "DestroyCallbackFunctionForEvent"; |
char szCreateButton[] = "CreateButton"; |
char szCreateButtonWithText[] = "CreateButtonWithText"; |
char szCreateProgressBar[] = "CreateProgressBar"; |
char szSetProgressBarPulse[] = "SetProgressBarPulse"; |
char szProgressBarSetText[] = "ProgressBarSetText"; |
char szProgressBarGetText[] = "ProgressBarGetText"; |
char szCreateHorizontalScrollBar[] = "CreateHorizontalScrollBar"; |
char szCreateVerticalScrollBar[] = "CreateVerticalScrollBar"; |
char szCreateScrolledWindow[] = "CreateScrolledWindow"; |
char szScrolledWindowPackControls[] = "ScrolledWindowPackControls"; |
char szCreateImage[] = "CreateImage"; |
char szCreateText[] = "CreateText"; |
char szTextBackgroundOn[] = "TextBackgroundOn"; |
char szTextBackgroundOff[] = "TextBackgroundOff"; |
char szLoadFont[] = "LoadFont"; |
char szFreeFont[] = "FreeFont"; |
export_t EXPORTS[]__asm__("EXPORTS") = |
{ |
{szLibGUIversion, LibGUIversion }, |
{szInitLibGUI, InitLibGUI }, |
{szLibGUImain, LibGUImain }, |
{szQuitLibGUI, QuitLibGUI }, |
{szCreateWindow, CreateWindow }, |
{szSetWindowSizeRequest, SetWindowSizeRequest }, |
{szPackControls, PackControls }, |
{szDestroyControl, DestroyControl }, |
{szSetControlSizeRequest, SetControlSizeRequest }, |
{szGetControlSizeX, GetControlSizeX }, |
{szGetControlSizeY, GetControlSizeY }, |
{szSetControlNewPosition, SetControlNewPosition }, |
{szGetControlPositionX, GetControlPositionX }, |
{szGetControlPositionY, GetControlPositionY }, |
{szSetFocuse, SetFocuse }, |
{szRedrawControl, RedrawControl }, |
{szSpecialRedrawControl, SpecialRedrawControl }, |
{szSetCallbackFunction, SetCallbackFunction }, |
{szBlockCallbackFunction, BlockCallbackFunction }, |
{szUnblockCallbackFunction, UnblockCallbackFunction }, |
{szSetIDL_Function, SetIDL_Function }, |
{szDestroyIDL_Function, DestroyIDL_Function }, |
{szSetTimerCallbackForFunction, SetTimerCallbackForFunction }, |
{szDestroyTimerCallbackForFunction, DestroyTimerCallbackForFunction }, |
{szSetCallbackFunctionForEvent, SetCallbackFunctionForEvent }, |
{szDestroyCallbackFunctionForEvent, DestroyCallbackFunctionForEvent }, |
{szCreateButton, CreateButton }, |
{szCreateButtonWithText, CreateButtonWithText }, |
{szCreateProgressBar, CreateProgressBar }, |
{szSetProgressBarPulse, SetProgressBarPulse }, |
{szProgressBarSetText, ProgressBarSetText }, |
{szProgressBarGetText, ProgressBarGetText }, |
{szCreateHorizontalScrollBar, CreateHorizontalScrollBar }, |
{szCreateVerticalScrollBar, CreateVerticalScrollBar }, |
{szCreateScrolledWindow, CreateScrolledWindow }, |
{szScrolledWindowPackControls, ScrolledWindowPackControls }, |
{szCreateImage, CreateImage }, |
{szCreateText, CreateText }, |
{szTextBackgroundOn, TextBackgroundOn }, |
{szTextBackgroundOff, TextBackgroundOff }, |
{szLoadFont, LoadFont }, |
{szFreeFont, FreeFont }, |
{NULL,NULL}, |
}; |
/programs/develop/libraries/libGUI/SRC/libGUI.h |
---|
0,0 → 1,580 |
/* |
service structures of libGUI |
*/ |
static DWORD ID; |
//screen's parameters |
#define BYTES_PER_PIXEL 4 |
//platform parameters |
#define KOLIBRIOS 1 |
//#define DEBUG |
//boolean constants |
#define TRUE 0x1 |
#define FALSE 0x0 |
//maximum callbacks for one check of callback |
#define MAX_CALLBACKS 255 |
///////////////////////////////////////////////////////////////////////// |
// libGUI sysyem messages types |
///////////////////////////////////////////////////////////////////////// |
#define MESSAGE_FULL_REDRAW_ALL 1 |
#define MESSAGE_KEYS_EVENT 2 |
#define MESSAGE_SPECIALIZED 3 |
#define MESSAGE_SET_FOCUSE 4 |
#define MESSAGE_CHANGE_FOCUSE 5 |
#define MESSAGE_MOUSE_EVENT 6 |
#define MESSAGE_CHANGE_POSITION_EVENT 7 |
#define MESSAGE_CHANGESIZE_EVENT 8 |
#define MESSAGE_CALL_TIMER_EVENT 9 |
#define MESSAGE_FULL_REDRAW_ALL_WITH_FINITION 10 |
#define MESSAGE_SET_MAIN_PARENT 11 |
#define MESSAGE_DESTROY_CONTROL -1 |
///////////////////////////////////////////////////////////////////////// |
// system flags of controls |
///////////////////////////////////////////////////////////////////////// |
#define FLAG_SHOW_CONTROL 0x1 |
#define FLAG_HIDE_CONTROL 0xfffe |
#define FLAG_FOCUSE_INPUT_SUPPOROTE 0x2 |
#define FLAG_FOCUSE_INPUT_NOTSUPPOROTE 0xfffd |
#define FLAG_FOCUSE_INPUT_ON 0x4 |
#define FLAG_FOCUSE_INPUT_OFF 0xfffb |
#define FLAG_CONNECT_EVENT_ON 0x8 |
#define FLAG_CONNECT_EVENT_OFF 0xfff7 |
#define FLAG_MOUSE_BLOCKED_ON 0x10 |
#define FLAG_MOUSE_BLOCKED_OFF 0xffef |
#define FLAG_GET_SPECIALIZED_MESSAGE_ON 0x20 |
#define FLAG_GET_SPECIALIZED_MESSAGE_OFF 0xffdf |
///////////////////////////////////////////////////////////////////////// |
// system flags of callback functions |
///////////////////////////////////////////////////////////////////////// |
#define FLAG_BLOCK_CALLBACK_ON 0x1 |
#define FLAG_BLOCK_CALLBACK_OFF 0xfe |
///////////////////////////////////////////////////////////////////////// |
// system flags of main wondow for timers |
///////////////////////////////////////////////////////////////////////// |
#define FLAG_TIMER_ON 0x1 |
#define FLAG_TIMER_OFF 0xfe |
///////////////////////////////////////////////////////////////////////// |
// system keys states |
///////////////////////////////////////////////////////////////////////// |
#define KEY_DOWN 16 |
#define KEY_UP 17 |
#define KEY_HOTKEY 18 |
///////////////////////////////////////////////////////////////////////// |
// system mouse buttons states |
///////////////////////////////////////////////////////////////////////// |
#define MOUSE_LEFT_BUTTON_DOWN 19 |
#define MOUSE_LEFT_BUTTON_UP 20 |
#define MOUSE_RIGHT_BUTTON_DOWN 21 |
#define MOUSE_RIGHT_BUTTON_UP 22 |
#define MOUSE_MIDDLE_BUTTON_DOWN 23 |
#define MOUSE_MIDDLE_BUTTON_UP 24 |
#define MOUSE_4_BUTTON_DOWN 25 |
#define MOUSE_4_BUTTON_UP 26 |
#define MOUSE_5_BUTTON_DOWN 27 |
#define MOUSE_5_BUTTON_UP 28 |
///////////////////////////////////////////////////////////////// |
// CONNECT EVENTS FOR CALLBACKs |
///////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////// |
// connect events for button |
//////////////////////////////////////////////////////////////// |
#define BUTTON_ENTER_EVENT 29 |
#define BUTTON_LEAVE_EVENT 30 |
#define BUTTON_PRESSED_EVENT 31 |
#define BUTTON_RELEASED_EVENT 32 |
//////////////////////////////////////////////////////////////// |
// connect events for button |
//////////////////////////////////////////////////////////////// |
#define SCROLLBAR_CHANGED_EVENT 33 |
//////////////////////////////////////////////////////////////// |
// connect events for main parent window |
//////////////////////////////////////////////////////////////// |
#define DELETE_EVENT 36 |
//////////////////////////////////////////////////////////////////// |
//screen buffer parameters |
//////////////////////////////////////////////////////////////////// |
#define DRAW_OUTPUT_SCREEN 0 |
#define DRAW_OUTPUT_BUFFER 1 |
static struct SCREEN |
{ |
DWORD bits_per_pixel; |
DWORD bytes_per_pixel; |
DWORD draw_output; |
int x; |
int y; |
int size_x; |
int size_y; |
int skin_height; |
int display_size_x; |
int display_size_y; |
char *buffer; |
}screen; |
//////////////////////////////////////////////////////////////// |
// header of parent of control |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct HEADERPARENT |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
DWORD **control_for_callback_function; |
DWORD **callback_for_control_callback; |
DWORD number_callbacks; |
DWORD *global_active_control_for_keys; |
DWORD *message; |
DWORD *timer_bk; |
DWORD *timer_fd; |
DWORD number_timers_for_controls; |
DWORD *calev_bk; |
DWORD *calev_fd; |
DWORD *IDL_func; |
DWORD *IDL_func_data; |
}; |
#pragma pack(pop) |
typedef struct HEADERPARENT parent_t; |
//////////////////////////////////////////////////////////////// |
// header of control |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct HEADER |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
}; |
#pragma pack(pop) |
typedef struct HEADER header_t; |
//////////////////////////////////////////////////////////////// |
// callback structure for callback function of control |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct CALLBACK |
{ |
DWORD *clb_bk; |
DWORD *clb_fd; |
DWORD *clb_control; |
DWORD *func; |
DWORD *func_data; |
DWORD connect_event; |
DWORD flags; |
}; |
#pragma pack(pop) |
typedef struct CALLBACK gui_callback_t; |
//////////////////////////////////////////////////////////////// |
// timer |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct TIMER |
{ |
DWORD *tmr_bk; |
DWORD *tmr_fd; |
DWORD *tmr_parent; |
DWORD *func; |
DWORD *func_data; |
DWORD last_time; |
DWORD time_tick; |
DWORD flags; |
}; |
#pragma pack(pop) |
typedef struct TIMER gui_timer_t; |
//////////////////////////////////////////////////////////////// |
// structure for callback events |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct CALLBACKEVENT |
{ |
DWORD *calev_bk; |
DWORD *calev_fd; |
DWORD *calev_parent; |
DWORD *func; |
DWORD *func_data; |
DWORD event_type; |
}; |
#pragma pack(pop) |
typedef struct CALLBACKEVENT gui_callbackevent_t; |
//////////////////////////////////////////////////////////////// |
// structure for callback events |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct FINITION |
{ |
DWORD x; |
DWORD y; |
DWORD sizex; |
DWORD sizey; |
char flags; |
}; |
#pragma pack(pop) |
typedef struct FINITION finition_t; |
//////////////////////////////////////////////////////////////// |
// type of data - structure message |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct MESSAGE |
{ |
DWORD type; |
DWORD arg1; |
DWORD arg2; |
DWORD arg3; |
DWORD arg4; |
}; |
#pragma pack(pop) |
typedef struct MESSAGE gui_message_t; |
//////////////////////////////////////////////////////////////// |
// prototype of functions |
//////////////////////////////////////////////////////////////// |
void (*ControlProc)(void *Control,gui_message_t *message); |
void (*CallbackFunction)(header_t *Control,void *data); |
void (*TimerCallbackFunction)(void *data); |
void (*CallbackFunctionForEvent)(gui_message_t *message,void *data); |
void (*IDL_Function)(void *data); |
//////////////////////////////////////////////////////////////// |
// button |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct ControlButton |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
//button's data |
unsigned char btn_flags; }; |
#pragma pack(pop) |
typedef struct ControlButton gui_button_t; |
// information for creating control Button |
#pragma pack(push,1) |
struct ButtonData |
{ |
int x; |
int y; |
int width; |
int height; |
}; |
#pragma pack(pop) |
typedef struct ButtonData gui_button_data_t; |
//////////////////////////////////////////////////////////////// |
// scroller |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct ControlScrollBar |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
//scroll bar's data |
float ruller_size; |
float ruller_pos; |
float ruller_step; |
unsigned char scb_flags; |
}; |
#pragma pack(pop) |
typedef struct ControlScrollBar gui_scroll_bar_t; |
#pragma pack(push,1) |
struct ScrollBarData |
{ |
int x; |
int y; |
int width; |
int height; |
float ruller_size; |
float ruller_pos; |
float ruller_step; |
}; |
#pragma pack(pop) |
typedef struct ScrollBarData gui_scroll_bar_data_t; |
//////////////////////////////////////////////////////////////// |
// progressbar |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct ControlProgressBar |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
//progress bar's data |
float progress; |
unsigned char prb_flags; |
}; |
#pragma pack(pop) |
typedef struct ControlProgressBar gui_progress_bar_t; |
#pragma pack(push,1) |
struct ProgressBarData |
{ |
int x; |
int y; |
int width; |
int height; |
float progress; |
}; |
#pragma pack(pop) |
typedef struct ProgressBarData gui_progress_bar_data_t; |
//////////////////////////////////////////////////////////////// |
// scrolled window |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct ControlScrolledWindow |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
//scrolled windows's data |
DWORD virtual_x; |
DWORD virtual_y; |
DWORD virtual_sizex; |
DWORD virtual_sizey; |
DWORD *virtual_controls_x; |
DWORD *virtual_controls_y; |
DWORD number_virtual_controls; |
DWORD scroll_arrea_sizex; |
DWORD scroll_arrea_sizey; |
DWORD *horizontal_scroll; |
DWORD *vertical_scroll; |
unsigned char scw_flags; |
}; |
#pragma pack(pop) |
typedef struct ControlScrolledWindow gui_scrolled_window_t; |
#pragma pack(push,1) |
struct ScrolledWindowData |
{ |
int x; |
int y; |
int width; |
int height; |
}; |
#pragma pack(pop) |
typedef struct ScrolledWindowData gui_scrolled_window_data_t; |
//////////////////////////////////////////////////////////////// |
// image |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct ControlImage |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
char bits_per_pixel; |
char bytes_per_pixel; |
char *img; |
}; |
#pragma pack(pop) |
typedef struct ControlImage gui_image_t; |
#pragma pack(push,1) |
struct ImageData |
{ |
int x; |
int y; |
int width; |
int height; |
char bits_per_pixel; |
}; |
#pragma pack(pop) |
typedef struct ImageData gui_image_data_t; |
//////////////////////////////////////////////////////////////// |
// text |
//////////////////////////////////////////////////////////////// |
#pragma pack(push,1) |
struct ControlText |
{ |
DWORD *ctrl_proc; |
DWORD *ctrl_fd; |
DWORD *ctrl_bk; |
DWORD *child_fd; |
DWORD *child_bk; |
DWORD *parent; |
DWORD *main_parent; |
DWORD ctrl_x; |
DWORD ctrl_y; |
DWORD ctrl_sizex; |
DWORD ctrl_sizey; |
DWORD ctrl_ID; |
DWORD *active_control_for_keys; |
DWORD *active_control_for_mouse; |
DWORD *callback; |
DWORD *finition; |
DWORD *timer; |
DWORD flags; |
DWORD *font; |
DWORD color; |
DWORD background_color; |
char *text; |
BYTE txt_flags; |
}; |
#pragma pack(pop) |
typedef struct ControlText gui_text_t; |
#pragma pack(push,1) |
struct TextData |
{ |
int x; |
int y; |
DWORD *font; |
DWORD color; |
DWORD background_color; |
char background; |
char *text; |
}; |
#pragma pack(pop) |
typedef struct TextData gui_text_data_t; |
///////////////////////////////////////////////////////////////////////////// |
// prototips of some service functions |
///////////////////////////////////////////////////////////////////////////// |
char CheckCrossRectangles(int x1,int y1,int sizex1,int sizey1,int x2,int y2,int sizex2,int sizey2); |
/programs/develop/libraries/libGUI/SRC/libGUI_menegement.inc |
---|
0,0 → 1,1657 |
/* |
libGUI main part of code |
*/ |
//--------------------------------------------------------------------------------- |
// destroy_control for libGUI |
//--------------------------------------------------------------------------------- |
void DestroyControl(void *control_ptr) |
{ |
struct HEADER *Parent; |
struct HEADER *control; |
struct HEADER *seek_control; |
struct HEADER *exchange_control; |
struct HEADER *last_control; |
struct HEADER *next_control; |
if (control_ptr==NULL) return; |
control=control_ptr; |
Parent=(struct HEADER *)control->parent; |
if (Parent->child_bk==Parent->child_fd) |
{ |
//parent have got alone child control |
if (Parent->child_bk==(DWORD*)control) |
{ |
//current control is child control of parent |
#ifdef DEBUG |
printf("\ndestroyed control=%d parent=%d ID=%d",(int)control,(int)Parent,(int)control->ctrl_ID); |
#endif |
free(control); |
Parent->child_bk=(DWORD*)NULL; |
Parent->child_fd=(DWORD*)NULL; |
} |
return; |
} |
seek_control=(struct HEADER*)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control==control) |
{ |
//delete control from control's stack |
last_control=(struct HEADER*)seek_control->ctrl_bk; |
next_control=(struct HEADER*)seek_control->ctrl_fd; |
if ((last_control!=Parent) && (next_control!=NULL)) |
{//deliting control isn't first control and isn't endest of parent |
next_control->ctrl_bk=(DWORD*)last_control; |
last_control->ctrl_fd=(DWORD*)next_control; |
} |
else |
{ |
if (last_control==Parent) |
{//deliting control is first control of Parend |
Parent->child_bk=(DWORD*)next_control; |
next_control->ctrl_bk=(DWORD*)Parent; |
if (next_control->ctrl_fd==(DWORD*)NULL) |
{ |
Parent->child_fd=(DWORD*)next_control; |
Parent->child_bk=(DWORD*)next_control; |
} |
} |
if (next_control==(struct HEADER*)NULL) |
{ |
//there isn't next controls |
last_control->ctrl_fd=(DWORD*)NULL; |
Parent->ctrl_fd=(DWORD*)last_control; |
} |
} |
#ifdef DEBUG |
printf("\ndestroyed control=%d parent=%d ID=%d",(int)control,(int)Parent,(int)control->ctrl_ID); |
#endif |
free(control); |
break; |
} |
exchange_control=(struct HEADER*)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
} |
//--------------------------------------------------------------------------------- |
// create new timer for parent window |
//--------------------------------------------------------------------------------- |
void *CreateTimerForParentWindow(parent_t *parent) |
{ |
struct TIMER *timer; |
struct TIMER *backward_timer; |
timer=malloc(sizeof(struct TIMER)); |
timer->tmr_parent=(DWORD*)parent; |
if (parent->timer_bk==(DWORD*)NULL) |
{//not yet timers |
parent->timer_bk=(DWORD*)timer; |
parent->timer_fd=(DWORD*)timer; |
timer->tmr_bk=(DWORD*)parent; |
timer->tmr_fd=(DWORD*)NULL; |
} |
else |
{ |
backward_timer=(struct TIMER*)parent->timer_fd; |
parent->timer_fd=(DWORD*)timer; |
backward_timer->tmr_fd=(DWORD*)timer; |
timer->tmr_bk=(DWORD*)backward_timer; |
timer->tmr_fd=(DWORD*)NULL; |
} |
return(timer); |
} |
//--------------------------------------------------------------------------------- |
// destroy timer for parent window |
//--------------------------------------------------------------------------------- |
void DestroyTimerCallbackForFunction(struct TIMER *timer) |
{ |
struct HEADERPARENT *Parent; |
struct TIMER *seek_timer; |
struct TIMER *exchange_timer; |
struct TIMER *last_timer; |
struct TIMER *next_timer; |
if (timer==(struct TIMER*)NULL) return; |
Parent=(struct HEADERPARENT *)timer->tmr_parent; |
if (Parent->timer_bk==Parent->timer_fd) |
{ |
//parent have got alone timer |
if (Parent->timer_bk==(DWORD*)timer) |
{ |
Parent->timer_bk=(DWORD*)NULL; |
Parent->timer_fd=(DWORD*)NULL; |
#ifdef DEBUG |
printf("\ndestroyed timer %d parent window %d",(int)timer,(int)timer->tmr_parent); |
#endif |
free(timer); |
return; |
} |
return; |
} |
seek_timer=(struct TIMER*)Parent->timer_bk; |
while(seek_timer!=(struct TIMER*)NULL) |
{ |
if (seek_timer==timer) |
{ |
//delete timer from timers's stack |
last_timer=(struct TIMER*)seek_timer->tmr_bk; |
next_timer=(struct TIMER*)seek_timer->tmr_fd; |
if ((last_timer!=(struct TIMER*)Parent) && (next_timer!=(struct TIMER*)NULL)) |
{//deliting timer isn't first timer and isn't endest |
next_timer->tmr_bk=(DWORD*)last_timer; |
last_timer->tmr_fd=(DWORD*)next_timer; |
} |
else |
{ |
if (last_timer==(struct TIMER*)Parent) |
{//deliting timer is first timer of Parend |
Parent->timer_bk=(DWORD*)next_timer; |
next_timer->tmr_bk=(DWORD*)Parent; |
if (next_timer->tmr_fd==(DWORD*)NULL) |
{ |
Parent->timer_fd=(DWORD*)next_timer; |
Parent->timer_bk=(DWORD*)next_timer; |
} |
} |
if (next_timer==(struct TIMER*)NULL) |
{ |
//there isn't next controls |
last_timer->tmr_fd=(DWORD*)NULL; |
Parent->timer_fd=(DWORD*)last_timer; |
} |
} |
#ifdef DEBUG |
printf("\ndestroyed timer %d parent window %d",(int)timer,(int)timer->tmr_parent); |
#endif |
free(timer); |
break; |
} |
exchange_timer=(struct TIMER*)seek_timer->tmr_fd; |
seek_timer=exchange_timer; |
} |
} |
//--------------------------------------------------------------------------------- |
// create timer for function of parent window |
//--------------------------------------------------------------------------------- |
void *SetTimerCallbackForFunction(parent_t *parent_window,int time_tick,void *func,void *func_data) |
{ |
struct TIMER *timer; |
timer=CreateTimerForParentWindow(parent_window); |
timer->func=(DWORD*)func; |
timer->func_data=(DWORD*)func_data; |
timer->time_tick=(DWORD)time_tick; |
timer->last_time=gui_ksys_get_ticks(); |
timer->flags=timer->flags | FLAG_TIMER_ON; |
return(timer); |
} |
//--------------------------------------------------------------------------------- |
// create timer for control |
//--------------------------------------------------------------------------------- |
void *SetTimerCallbackForControl(int time_tick,void *func,void *func_data) |
{ |
struct TIMER *timer; |
timer=malloc(sizeof(struct TIMER)); |
timer->func=(DWORD*)func; |
timer->func_data=(DWORD*)func_data; |
timer->time_tick=(DWORD)time_tick; |
timer->last_time=gui_ksys_get_ticks(); |
timer->flags=timer->flags & FLAG_TIMER_OFF; |
return(timer); |
} |
//--------------------------------------------------------------------------------- |
// call timer |
//--------------------------------------------------------------------------------- |
void Timer(struct TIMER *timer) |
{ |
DWORD time,delta_time; |
time=gui_ksys_get_ticks(); |
delta_time=time-timer->last_time; |
if (delta_time>=timer->time_tick) |
{ |
TimerCallbackFunction=(void(*)(void *data))timer->func; |
TimerCallbackFunction(timer->func_data); |
timer->last_time=gui_ksys_get_ticks(); |
} |
} |
//--------------------------------------------------------------------------------- |
// create new callback for event |
//--------------------------------------------------------------------------------- |
void *CreateCallbackForEvent(parent_t *parent) |
{ |
gui_callbackevent_t *calev; |
gui_callbackevent_t *backward_calev; |
calev=malloc(sizeof(gui_callbackevent_t)); |
calev->calev_parent=(DWORD*)parent; |
if (parent->calev_bk==(DWORD*)NULL) |
{//not yet timers |
parent->calev_bk=(DWORD*)calev; |
parent->calev_fd=(DWORD*)calev; |
calev->calev_bk=(DWORD*)parent; |
calev->calev_fd=(DWORD*)NULL; |
} |
else |
{ |
backward_calev=(gui_callbackevent_t*)parent->calev_fd; |
parent->calev_fd=(DWORD*)calev; |
backward_calev->calev_fd=(DWORD*)calev; |
calev->calev_bk=(DWORD*)backward_calev; |
calev->calev_fd=(DWORD*)NULL; |
} |
return(calev); |
} |
//--------------------------------------------------------------------------------- |
// destroy callback function for eventcalev |
//--------------------------------------------------------------------------------- |
void DestroyCallbackFunctionForEvent(gui_callbackevent_t *calev) |
{ |
struct HEADERPARENT *Parent; |
struct CALLBACKEVENT *seek_calev; |
struct CALLBACKEVENT *exchange_calev; |
struct CALLBACKEVENT *last_calev; |
struct CALLBACKEVENT *next_calev; |
if (calev==(gui_callbackevent_t*)NULL) return; |
Parent=(parent_t*)calev->calev_parent; |
if (Parent->calev_bk==Parent->calev_fd) |
{ |
//parent have got alone timer |
if (Parent->calev_bk==(DWORD*)calev) |
{ |
free(calev); |
Parent->calev_bk=(DWORD*)NULL; |
Parent->calev_fd=(DWORD*)NULL; |
} |
return; |
} |
seek_calev=(struct CALLBACKEVENT*)Parent->calev_bk; |
while(seek_calev!=(struct CALLBACKEVENT*)NULL) |
{ |
if (seek_calev==calev) |
{ |
//delete timer from timers's stack |
last_calev=(struct CALLBACKEVENT*)seek_calev->calev_bk; |
next_calev=(struct CALLBACKEVENT*)seek_calev->calev_fd; |
if ((last_calev!=(struct CALLBACKEVENT*)Parent) && (next_calev!=(struct CALLBACKEVENT*)NULL)) |
{//deliting timer isn't first timer and isn't endest |
next_calev->calev_bk=(DWORD*)last_calev; |
last_calev->calev_fd=(DWORD*)next_calev; |
} |
else |
{ |
if (last_calev==(struct CALLBACKEVENT*)Parent) |
{//deliting timer is first timer of Parend |
Parent->calev_bk=(DWORD*)next_calev; |
next_calev->calev_bk=(DWORD*)Parent; |
if (next_calev->calev_fd==(DWORD*)NULL) |
{ |
Parent->calev_fd=(DWORD*)next_calev; |
Parent->calev_bk=(DWORD*)next_calev; |
} |
} |
if (next_calev==(struct CALLBACKEVENT*)NULL) |
{ |
//there isn't next controls |
last_calev->calev_fd=(DWORD*)NULL; |
Parent->calev_fd=(DWORD*)last_calev; |
} |
} |
free(calev); |
break; |
} |
exchange_calev=(struct CALLBACKEVENT*)seek_calev->calev_fd; |
seek_calev=exchange_calev; |
} |
} |
//--------------------------------------------------------------------------------- |
// create callback for messenger of events |
//--------------------------------------------------------------------------------- |
void *SetCallbackFunctionForEvent(parent_t *parent_window,int event_type,void *func,void *func_data) |
{ |
gui_callbackevent_t *calev; |
calev=CreateCallbackForEvent(parent_window); |
calev->func=(DWORD*)func; |
calev->func_data=(DWORD*)func_data; |
calev->event_type=(DWORD)event_type; |
return(calev); |
} |
//--------------------------------------------------------------------------------- |
// check cross control and mouse |
//--------------------------------------------------------------------------------- |
char CheckCrossBox(struct HEADER *control,int mouse_x,int mouse_y) |
{ |
struct FINITION *fin; |
int x,y,x2,y2; |
int xmin,xmax,ymin,ymax,sx,sy; |
fin=(struct FINITION*)control->finition; |
if (fin->flags & FINITION_ON) |
{ |
xmin=fin->x; |
xmax=fin->x+fin->sizex-1; |
ymin=fin->y; |
ymax=fin->y+fin->sizey-1; |
x=control->ctrl_x; |
y=control->ctrl_y; |
x2=x+control->ctrl_sizex-1; |
y2=y+control->ctrl_sizey-1; |
if (x2<xmin) return(FALSE); |
if (x>xmax) return(FALSE); |
if (y2<ymin) return(FALSE); |
if (y>ymax) return(FALSE); |
//finit x coordinates and sizex |
sx=x-xmin; |
if (sx>=0) |
{ |
if (x2>xmax) x2=xmax; |
} |
else |
{ |
x=xmin; |
if (x2>xmax) x2=xmax; |
} |
//finit y coordinates and sizey |
sy=y-ymin; |
if (sy>=0) |
{ |
if (y2>ymax) y2=ymax; |
} |
else |
{ |
y=ymin; |
if (y2>ymax) y2=ymax; |
} |
//check cross finited control with mouse |
if ((mouse_x>=x) && (mouse_x<=x2) && (mouse_y>=y) && (mouse_y<=y2)) |
return(TRUE); |
else |
return(FALSE); |
} |
else |
{ |
if ((mouse_x>=control->ctrl_x) && (mouse_x<=control->ctrl_x+control->ctrl_sizex) && |
(mouse_y>=control->ctrl_y) && (mouse_y<=control->ctrl_y+control->ctrl_sizey)) |
return(TRUE); |
else |
return(FALSE); |
} |
} |
//--------------------------------------------------------------------------------- |
// check cross two rectaangles |
//--------------------------------------------------------------------------------- |
char CheckCrossRectangles(int x1,int y1,int sizex1,int sizey1,int x2,int y2,int sizex2,int sizey2) |
{ |
int s; |
int xmax,ymax; |
xmax=x1+sizex1-1; |
ymax=y1+sizey1-1; |
//check x cross |
s=x2-x1; |
if (s>0) |
{//second rectangle have right position |
if (x2>xmax) return(FALSE); |
} |
if (s<0) |
{//second rectangle have left position |
s=-s; |
if (s>=sizex2) return(FALSE); |
} |
//check y cross |
s=y2-y1; |
if (s>0) |
{//second rectangle have down position |
if (y2>ymax) return(FALSE); |
} |
if (s<0) |
{//second rectangle have up position |
s=-s; |
if (s>=sizey2) return(FALSE); |
} |
return(TRUE); |
} |
//--------------------------------------------------------------------------------- |
// check full cross two rectaangles |
//--------------------------------------------------------------------------------- |
char CheckFullCrossRectangles(int x1,int y1,int sizex1,int sizey1,int x2,int y2,int sizex2,int sizey2) |
{ |
int s; |
int xmax,ymax; |
xmax=x1+sizex1-1; |
ymax=y1+sizey1-1; |
if (x2>=x1 && x2+sizex2-1<=xmax && y2>=y1 && y2+sizey2-1<=ymax) return(TRUE); |
else return(FALSE); |
} |
//--------------------------------------------------------------------------------- |
// send message to controls |
//--------------------------------------------------------------------------------- |
void SendMessage(struct HEADER *Parent,struct MESSAGE *message) |
{ |
struct HEADER *seek_control; |
struct HEADER *exchange_control; |
struct HEADER *parent; |
struct HEADERPARENT *main_parent; |
struct MESSAGE local_service_message; |
struct HEADER *active_control_for_keys; |
struct HEADER *active_control_for_mouse; |
char cross; |
//Parent haven't got child controls |
if ((Parent->child_bk==NULL) && (Parent->child_fd==NULL)) return; |
//load main parent |
main_parent=(struct HEADERPARENT*)Parent->main_parent; |
//load active controls from Parent |
active_control_for_keys=(struct HEADER*)Parent->active_control_for_keys; |
active_control_for_mouse=(struct HEADER*)Parent->active_control_for_mouse; |
//Parent have got alon child control |
if (Parent->child_bk==Parent->child_fd) |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//send message redraw to all child controls |
if (seek_control->flags & FLAG_SHOW_CONTROL) ControlProc(seek_control,message); |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
//send message finited redraw to all child controls |
if (seek_control->flags & FLAG_SHOW_CONTROL) ControlProc(seek_control,message); |
break; |
} |
case MESSAGE_KEYS_EVENT: |
{ //change active control for keyboard by TAB press |
if ((message->arg1==KEY_DOWN) && (message->arg2==SC_TAB)) |
{ |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
if (active_control_for_keys==seek_control) |
{//focuse of input set for current control |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
local_service_message.arg1=FALSE; |
active_control_for_keys->flags=active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
parent=(struct HEADER*)active_control_for_keys->parent; |
seek_control=parent; |
do |
{ |
if (parent==(struct HEADER*)main_parent) break; |
//if next control NULL go to parent |
if (seek_control==(struct HEADER*)NULL) seek_control=parent; |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
if (seek_control==(struct HEADER*)NULL) |
parent=(struct HEADER*)parent->parent; |
} |
while((seek_control==(struct HEADER*)NULL) || |
((seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE)==FALSE)); |
if (parent==(struct HEADER*)main_parent) |
{ |
//find first control of main parent with focuse of input supporote |
seek_control=(struct HEADER *)main_parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) break; |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
main_parent->active_control_for_keys=(DWORD*)seek_control; |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
//send message enable focuse of input to control |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
local_service_message.arg1=FALSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=(struct HEADER*)NULL; |
break; |
} |
if (seek_control!=(struct HEADER*)NULL) |
{ |
parent=(struct HEADER*)seek_control->parent; |
parent->active_control_for_keys=(DWORD*)seek_control; |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
//send message enable focuse of input to control |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
local_service_message.arg1=FALSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=(struct HEADER*)NULL; |
Parent->active_control_for_keys=(DWORD*)active_control_for_keys; |
break; |
} |
} |
else |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
local_service_message.arg1=FALSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=seek_control; |
Parent->active_control_for_keys=(DWORD*)active_control_for_keys; |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
} |
} |
} |
//send message of keys only to active control |
if (active_control_for_keys!=NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_keys->ctrl_proc; |
ControlProc(active_control_for_keys,message); |
} |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ |
//send specialized message to all child controls |
ControlProc(seek_control,message); |
break; |
} |
case MESSAGE_MOUSE_EVENT: |
{ |
if (seek_control->flags & FLAG_MOUSE_BLOCKED_ON) break; |
if (message->arg3==MOUSE_LEFT_BUTTON_DOWN) |
{ |
if (active_control_for_mouse!=NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_mouse->ctrl_proc; |
ControlProc(active_control_for_mouse,message); |
break; |
} |
} |
else |
{ |
if (active_control_for_mouse!=NULL) {active_control_for_mouse=NULL;} |
} |
cross=FALSE; |
if (CheckCrossBox(seek_control,message->arg1,message->arg2)==TRUE) |
{ |
if (message->arg3==MOUSE_LEFT_BUTTON_DOWN) |
{ |
cross=TRUE; |
active_control_for_mouse=seek_control; |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
parent=(struct HEADER*)seek_control->parent; |
if (parent->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
active_control_for_keys=(struct HEADER*)main_parent->global_active_control_for_keys; |
if (active_control_for_keys!=(struct HEADER*)NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
active_control_for_keys->flags= |
active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
} |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
Parent->active_control_for_keys=(DWORD*)seek_control; |
} |
} |
} |
} |
if ((cross==FALSE) && (message->arg3==MOUSE_LEFT_BUTTON_DOWN)) |
{ |
if (active_control_for_keys!=NULL) |
{//disable focuse of input for active control of keys |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
active_control_for_keys->flags=active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
} |
} |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
ControlProc(seek_control,message); |
break; |
} |
case MESSAGE_CALL_TIMER_EVENT: |
{ |
ControlProc(seek_control,message); |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
//send message to control for destroing child controls |
ControlProc(seek_control,message); |
DestroyControl(seek_control); |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
ControlProc(seek_control,message); |
break; |
} |
default:break; |
} |
} |
else |
{ |
switch(message->type) |
{ |
case MESSAGE_FULL_REDRAW_ALL: |
{ |
//send message redraw to all child controls of Parent |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control->flags & FLAG_SHOW_CONTROL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
} |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_FULL_REDRAW_ALL_WITH_FINITION: |
{ |
//send message redraw to all child controls of Parent |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control->flags & FLAG_SHOW_CONTROL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
} |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_KEYS_EVENT: |
{ |
if ((message->arg1==KEY_DOWN) && (message->arg2==SC_TAB)) |
{ //change active control for keyboard by TAB press |
if (active_control_for_keys==NULL) |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
if ((seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE)==FALSE) |
{ //find first control of parend with supporote of input |
while(seek_control->ctrl_fd!=(DWORD*)NULL) |
{ |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
active_control_for_keys=seek_control; |
main_parent->global_active_control_for_keys= |
(DWORD*)active_control_for_keys; |
Parent->active_control_for_keys=(DWORD*)active_control_for_keys; |
break; |
} |
} |
if (active_control_for_keys!=NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
} |
} |
else |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=seek_control; |
main_parent->global_active_control_for_keys=(DWORD*)active_control_for_keys; |
Parent->active_control_for_keys=(DWORD*)active_control_for_keys; |
} |
} |
else |
{ |
if (active_control_for_keys==(struct HEADER*)main_parent->global_active_control_for_keys) |
{ |
seek_control=active_control_for_keys; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
if (seek_control==(struct HEADER*)NULL) |
{ //send message disable focuse of input to current control |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
active_control_for_keys->flags= |
active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
//back into main parent of tree and find next not NULL control |
parent=(struct HEADER*)active_control_for_keys->parent; |
do |
{ |
if (parent==(struct HEADER*)main_parent) break; |
//if next control NULL go to parent |
if (seek_control==(struct HEADER*)NULL) seek_control=parent; |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
if (seek_control==(struct HEADER*)NULL) |
parent=(struct HEADER*)parent->parent; |
} |
while((seek_control==(struct HEADER*)NULL) || |
((seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE)==FALSE)); |
if (parent==(struct HEADER*)main_parent) |
{ |
//find first control of main parent with focuse of input supporote |
seek_control=(struct HEADER *)main_parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
break; |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
main_parent->active_control_for_keys=(DWORD*)seek_control; |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
//send message enable focuse of input to control |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=(struct HEADER*)NULL; |
break; |
} |
if (seek_control!=(struct HEADER*)NULL) |
{ |
parent=(struct HEADER*)seek_control->parent; |
parent->active_control_for_keys=(DWORD*)seek_control; |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
//send message enable focuse of input to control |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=(struct HEADER*)NULL; |
Parent->active_control_for_keys=(DWORD*)active_control_for_keys; |
break; |
} |
} |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
active_control_for_keys->flags= |
active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=seek_control; |
main_parent->global_active_control_for_keys= |
(DWORD*)active_control_for_keys; |
Parent->active_control_for_keys=(DWORD*)active_control_for_keys; |
break; |
} |
} |
} |
} |
} |
//send message of keys only to active control |
if (active_control_for_keys!=NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_keys->ctrl_proc; |
ControlProc(active_control_for_keys,message); |
} |
break; |
} |
case MESSAGE_SPECIALIZED: |
{ |
//send specialized message to all child controls |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_MOUSE_EVENT: |
{ |
if (message->arg3==MOUSE_LEFT_BUTTON_DOWN) |
{ |
if (active_control_for_mouse!=NULL) |
{ |
if (active_control_for_mouse->flags & FLAG_MOUSE_BLOCKED_ON) break; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_mouse->ctrl_proc; |
ControlProc(active_control_for_mouse,message); |
break; |
} |
} |
else |
{ |
if (active_control_for_mouse!=NULL) {active_control_for_mouse=NULL;} |
} |
cross=FALSE; |
seek_control=(struct HEADER*)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (CheckCrossBox(seek_control,message->arg1,message->arg2)==TRUE && |
(seek_control->flags & FLAG_MOUSE_BLOCKED_ON)==FALSE) |
{ |
if (message->arg3==MOUSE_LEFT_BUTTON_DOWN) |
{ |
cross=TRUE; |
active_control_for_mouse=seek_control; |
if (active_control_for_mouse->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
//set focuse of input for new active control |
active_control_for_mouse->flags=active_control_for_mouse->flags | FLAG_FOCUSE_INPUT_ON; |
if (active_control_for_keys!=NULL) |
{ |
if (active_control_for_keys!=seek_control) |
{ |
//check seek control for supporote focuse of input |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
//check parent for supporote focuse of input |
parent=(struct HEADER*)seek_control->parent; |
if (parent->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
local_service_message.arg1=FALSE; |
active_control_for_keys->flags= |
active_control_for_keys->flags & |
FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
local_service_message.arg1=FALSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
active_control_for_keys=seek_control; |
main_parent->global_active_control_for_keys= |
(DWORD*)active_control_for_keys; |
Parent->active_control_for_keys= |
(DWORD*)active_control_for_keys; |
} |
} |
} |
} |
else |
{ |
//check seek control for supporote focuse of input |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
//check parent for supporote focuse of input |
parent=(struct HEADER*)seek_control->parent; |
if (parent->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
active_control_for_keys=(struct HEADER*)main_parent->global_active_control_for_keys; |
if (active_control_for_keys!=NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
active_control_for_keys->flags= |
active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
} |
ControlProc=(void (*)(void *Control,struct MESSAGE *message)) |
seek_control->ctrl_proc; |
local_service_message.type=MESSAGE_SET_FOCUSE; |
seek_control->flags=seek_control->flags | FLAG_FOCUSE_INPUT_ON; |
ControlProc(seek_control,&local_service_message); |
main_parent->global_active_control_for_keys=(DWORD*)seek_control; |
Parent->active_control_for_keys=(DWORD*)seek_control; |
} |
} |
} |
} |
} |
} |
if ((seek_control->flags & FLAG_MOUSE_BLOCKED_ON)==FALSE) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
} |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
if ((cross==FALSE) && (message->arg3==MOUSE_LEFT_BUTTON_DOWN)) |
{ |
if (active_control_for_keys!=NULL) |
{//disable focuse of input for active control of keys |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))active_control_for_keys->ctrl_proc; |
local_service_message.type=MESSAGE_CHANGE_FOCUSE; |
active_control_for_keys->flags=active_control_for_keys->flags & FLAG_FOCUSE_INPUT_OFF; |
ControlProc(active_control_for_keys,&local_service_message); |
main_parent->global_active_control_for_keys=(DWORD*)NULL; |
Parent->active_control_for_keys=(DWORD*)NULL; |
} |
} |
break; |
} |
case MESSAGE_CHANGE_POSITION_EVENT: |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_CALL_TIMER_EVENT: |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_SET_FOCUSE: |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
break; |
} |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_CHANGE_FOCUSE: |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
if (seek_control->flags & FLAG_FOCUSE_INPUT_SUPPOROTE) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
ControlProc(seek_control,message); |
break; |
} |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_DESTROY_CONTROL: |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ //befor delet control get next control of parent |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
//send message to control for destroyng child controls |
ControlProc(seek_control,message); |
DestroyControl(seek_control); |
seek_control=exchange_control; |
} |
break; |
} |
case MESSAGE_SET_MAIN_PARENT: |
{ |
seek_control=(struct HEADER *)Parent->child_bk; |
while(seek_control!=(struct HEADER*)NULL) |
{ |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))seek_control->ctrl_proc; |
//send message to control for destroyng child controls |
ControlProc(seek_control,message); |
seek_control->main_parent=(DWORD*)message->arg1; |
exchange_control=(struct HEADER *)seek_control->ctrl_fd; |
seek_control=exchange_control; |
} |
break; |
} |
default:break; |
} |
} |
Parent->active_control_for_mouse=(DWORD*)active_control_for_mouse; |
} |
//--------------------------------------------------------------------------------- |
// pack control_child in control_parent for libGUI |
//--------------------------------------------------------------------------------- |
//add new control for Parent |
void PackControls(void *parent,void *Control) |
{ |
struct HEADER *Parent; |
struct HEADER *last_control; |
struct HEADER *control; |
struct MESSAGE message; |
Parent=(struct HEADER *)parent; |
control=(struct HEADER *)Control; |
//set control's dependeces |
if (Parent->child_bk==NULL) |
{ |
//create first child control for parent |
Parent->child_bk=(DWORD*)control; |
Parent->child_fd=(DWORD*)control; |
//init control |
control->parent=(DWORD*)Parent; |
control->ctrl_bk=(DWORD*)Parent;//last control is parent |
control->ctrl_fd=(DWORD*)NULL;//haven't next control |
} |
else |
{ |
//set new control as endest child control of parent |
last_control=(struct HEADER*)Parent->child_fd; |
Parent->child_fd=(DWORD*)control; |
last_control->ctrl_fd=(DWORD*)control; |
control->ctrl_bk=(DWORD*)last_control; |
control->ctrl_fd=(DWORD*)NULL; |
control->parent=(DWORD*)Parent; |
} |
//finite control's coordinates and size |
control->ctrl_x=control->ctrl_x+Parent->ctrl_x; |
control->ctrl_y=control->ctrl_y+Parent->ctrl_y; |
if (control->ctrl_sizex<=1) {control->ctrl_sizex=1;} |
if (control->ctrl_sizey<=1) {control->ctrl_sizey=1;} |
message.type=(DWORD)MESSAGE_CHANGE_POSITION_EVENT; |
message.arg1=Parent->ctrl_x; |
message.arg2=Parent->ctrl_y; |
//send message change position to child controls |
SendMessage(control,&message); |
if (Parent->main_parent!=(DWORD*)NULL) |
{ |
//tell all child controls of main parent who is main parent |
message.type=MESSAGE_SET_MAIN_PARENT; |
message.arg1=(DWORD)Parent->main_parent; |
SendMessage((struct HEADER *)Parent,&message); |
} |
} |
//--------------------------------------------------------------------------------- |
// show/hide controls |
//--------------------------------------------------------------------------------- |
void ShowControl(void *Control) |
{ |
struct HEADER *control; |
control=(struct HEADER *)Control; |
control->flags=control->flags | FLAG_SHOW_CONTROL; |
} |
void HideControl(void *Control) |
{ |
struct HEADER *control; |
control=(struct HEADER *)Control; |
control->flags=control->flags & FLAG_HIDE_CONTROL; |
} |
//--------------------------------------------------------------------------------- |
// redraw control |
//--------------------------------------------------------------------------------- |
void RedrawControl(void *Control) |
{ |
struct HEADER *control; |
struct MESSAGE message; |
control=(struct HEADER*)Control; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))control->ctrl_proc; |
message.type=MESSAGE_FULL_REDRAW_ALL; |
ControlProc(control,&message); |
} |
//--------------------------------------------------------------------------------- |
// special redraw of control |
//--------------------------------------------------------------------------------- |
void SpecialRedrawControl(void *Control) |
{ |
struct HEADER *control; |
struct MESSAGE message; |
struct HEADERPARENT *main_parent; |
control=(struct HEADER*)Control; |
main_parent=(struct HEADERPARENT*)control->main_parent; |
control->flags=control->flags | FLAG_GET_SPECIALIZED_MESSAGE_ON; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))control->ctrl_proc; |
message.type=MESSAGE_SPECIALIZED; |
ControlProc((struct HEADER*)main_parent,&message); |
} |
//--------------------------------------------------------------------------------- |
// set new size for control |
//--------------------------------------------------------------------------------- |
void SetControlSizeRequest(void *Control,int new_size_x,int new_size_y) |
{ |
struct HEADER *control; |
struct HEADER *Parent; |
control=(struct HEADER*)Control; |
Parent=(struct HEADER*)control->parent; |
control->ctrl_sizex=(DWORD)new_size_x; |
control->ctrl_sizey=(DWORD)new_size_y; |
if ((control->ctrl_x+control->ctrl_sizex)>Parent->ctrl_sizex) |
{control->ctrl_sizex=Parent->ctrl_sizex-control->ctrl_x;} |
if ((control->ctrl_y+control->ctrl_sizey)>Parent->ctrl_sizey) |
{control->ctrl_sizey=Parent->ctrl_sizey-control->ctrl_y;} |
if (control->ctrl_sizex<=1) {control->ctrl_sizex=1;} |
if (control->ctrl_sizey<=1) {control->ctrl_sizey=1;} |
} |
//--------------------------------------------------------------------------------- |
// get size x of control |
//--------------------------------------------------------------------------------- |
int GetControlSizeX(void *Control) |
{ |
struct HEADER *control; |
control=(struct HEADER *)Control; |
return ((int)control->ctrl_sizex); |
} |
//--------------------------------------------------------------------------------- |
// get size y of control |
//--------------------------------------------------------------------------------- |
int GetControlSizeY(void *Control) |
{ |
struct HEADER *control; |
control=(struct HEADER *)Control; |
return ((int)control->ctrl_sizey); |
} |
//--------------------------------------------------------------------------------- |
// set new size for control |
//--------------------------------------------------------------------------------- |
void SetControlNewPosition(void *Control,int new_x,int new_y) |
{ |
struct HEADER *control; |
struct HEADER *Parent; |
struct MESSAGE message; |
parent_t *main_parent; |
int old_x; |
int old_y; |
control=(struct HEADER*)Control; |
/* |
main_parent=(parent_t*)control->main_parent; |
if (control->parent==(DWORD*)main_parent) |
{//check position of child control of main parent |
if (new_x+control->ctrl_sizex-1>screen.size_x) return; |
if (new_y+control->ctrl_sizey-1>screen.size_y) return; |
}*/ |
message.type=(DWORD)MESSAGE_CHANGE_POSITION_EVENT; |
message.arg1=(DWORD)(new_x-control->ctrl_x); |
message.arg2=(DWORD)(new_y-control->ctrl_y); |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))control->ctrl_proc; |
ControlProc(control,&message); |
} |
//--------------------------------------------------------------------------------- |
// get x position of control |
//--------------------------------------------------------------------------------- |
int GetControlPositionX(void *Control) |
{ |
struct HEADER *control; |
control=(struct HEADER *)Control; |
return ((int)control->ctrl_x); |
} |
//--------------------------------------------------------------------------------- |
// get y position of control |
//--------------------------------------------------------------------------------- |
int GetControlPositionY(void *Control) |
{ |
struct HEADER *control; |
control=(struct HEADER *)Control; |
return ((int)control->ctrl_y); |
} |
//--------------------------------------------------------------------------------- |
// set focuse of input for control |
//--------------------------------------------------------------------------------- |
void *SetFocuse(void *Control) |
{ |
struct HEADER *control; |
struct HEADERPARENT *main_parent; |
struct HEADER *old_control; |
struct MESSAGE *message; |
//new active control with focuse |
control=(struct HEADER*)Control; |
main_parent=(struct HEADERPARENT*)control->main_parent; |
if (main_parent==(struct HEADERPARENT*)NULL) return; |
//old control with focuse |
old_control=(struct HEADER*)main_parent->global_active_control_for_keys; |
if (old_control!=(struct HEADER*)NULL) |
{ |
message->type=MESSAGE_CHANGE_FOCUSE; |
message->arg1=FALSE; |
message->arg2=FALSE; |
message->arg3=FALSE; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))old_control->ctrl_proc; |
ControlProc(old_control,message); |
} |
message->type=MESSAGE_SET_FOCUSE; |
message->arg1=FALSE; |
message->arg2=FALSE; |
message->arg3=FALSE;; |
ControlProc=(void (*)(void *Control,struct MESSAGE *message))control->ctrl_proc; |
ControlProc(control,message); |
return(old_control); |
} |
//--------------------------------------------------------------------------------- |
// set callback function for control |
//--------------------------------------------------------------------------------- |
void *SetCallbackFunction(void *Control,int event_name,void *callback_func,void *callback_func_data) |
{ |
struct HEADER *control; |
struct CALLBACK *seek_callback; |
struct CALLBACK *exchange_callback; |
struct CALLBACK *new_callback; |
control=(struct HEADER *)Control; |
seek_callback=(struct CALLBACK*)control->callback; |
if (seek_callback==(struct CALLBACK *)NULL) |
{ //callback function creating at first |
new_callback=malloc(sizeof(struct CALLBACK)); |
control->callback=(DWORD*)new_callback; |
new_callback->clb_bk=(DWORD*)control; |
new_callback->clb_fd=(DWORD*)NULL; |
new_callback->clb_control=(DWORD*)control; |
new_callback->connect_event=(DWORD)event_name; |
new_callback->func=(DWORD*)callback_func; |
new_callback->func_data=(DWORD*)callback_func_data; |
new_callback->flags=0x0; |
} |
else |
{ |
while(seek_callback!=(struct CALLBACK*)NULL) |
{ |
if (seek_callback->clb_fd==(DWORD*)NULL) |
{//create new callback control for callback function |
new_callback=malloc(sizeof(struct CALLBACK)); |
seek_callback->clb_fd=(DWORD*)new_callback; |
new_callback->clb_bk=(DWORD*)seek_callback; |
new_callback->clb_fd=(DWORD*)NULL; |
new_callback->clb_control=(DWORD*)control; |
new_callback->connect_event=(DWORD)event_name; |
new_callback->func=(DWORD*)callback_func; |
new_callback->func_data=(DWORD*)callback_func_data; |
new_callback->flags=0x0; |
break; |
} |
exchange_callback=(struct CALLBACK*)seek_callback->clb_fd; |
seek_callback=exchange_callback; |
} |
} |
#ifdef DEBUG |
printf("\ncreated callback %d for function %d data %d", |
(DWORD)new_callback, |
(DWORD)callback_func, |
(DWORD)callback_func_data); |
#endif |
return(new_callback); |
} |
//--------------------------------------------------------------------------------- |
// block current callback function for control |
//--------------------------------------------------------------------------------- |
void BlockCallbackFunction(void *Control,void *callback_ID) |
{ |
struct HEADER *control; |
struct CALLBACK *seek_callback; |
struct CALLBACK *exchange_callback; |
struct CALLBACK *unknown_callback; |
control=(struct HEADER *)Control; |
seek_callback=(struct CALLBACK *)control->callback; |
unknown_callback=(struct CALLBACK*)callback_ID; |
while(seek_callback!=(struct CALLBACK*)NULL) |
{ |
if (seek_callback==unknown_callback) |
{ |
unknown_callback->flags=unknown_callback->flags | FLAG_BLOCK_CALLBACK_ON; |
break; |
} |
exchange_callback=(struct CALLBACK*)seek_callback->clb_fd; |
seek_callback=exchange_callback; |
} |
} |
//--------------------------------------------------------------------------------- |
// unblock current callback function for control |
//--------------------------------------------------------------------------------- |
void UnblockCallbackFunction(void *Control,void *callback_ID) |
{ |
struct HEADER *control; |
struct CALLBACK *seek_callback; |
struct CALLBACK *exchange_callback; |
struct CALLBACK *unknown_callback; |
control=(struct HEADER *)Control; |
seek_callback=(struct CALLBACK *)control->callback; |
unknown_callback=(struct CALLBACK*)callback_ID; |
while(seek_callback!=(struct CALLBACK*)NULL) |
{ |
if (seek_callback==unknown_callback) |
{ |
unknown_callback->flags=unknown_callback->flags & FLAG_BLOCK_CALLBACK_OFF; |
break; |
} |
exchange_callback=(struct CALLBACK*)seek_callback->clb_fd; |
seek_callback=exchange_callback; |
} |
} |
//--------------------------------------------------------------------------------- |
// check callback event for control |
//--------------------------------------------------------------------------------- |
void *ControlCheckCallbackEvent(void *Control,DWORD event) |
{ |
struct HEADER *control; |
struct CALLBACK *seek_callback; |
struct CALLBACK *exchange_callback; |
control=(struct HEADER *)Control; |
seek_callback=(struct CALLBACK *)control->callback; |
while(seek_callback!=(struct CALLBACK*)NULL) |
{ |
if ((seek_callback->flags & FLAG_BLOCK_CALLBACK_ON)==FALSE) |
{ |
if (seek_callback->connect_event==event) return (seek_callback); |
} |
exchange_callback=(struct CALLBACK*)seek_callback->clb_fd; |
seek_callback=exchange_callback; |
} |
return(NULL); |
} |
//--------------------------------------------------------------------------------- |
// set IDL function for libGUI |
//--------------------------------------------------------------------------------- |
void SetIDL_Function(parent_t *parent,void *function,void *function_data) |
{ |
parent->IDL_func=(DWORD*)function; |
parent->IDL_func_data=(DWORD*)function_data; |
} |
//--------------------------------------------------------------------------------- |
// destroy IDL function for libGUI |
//--------------------------------------------------------------------------------- |
void DestroyIDL_Function(parent_t *parent) |
{ |
parent->IDL_func=(DWORD*)NULL; |
} |
//--------------------------------------------------------------------------------- |
// initialize libGUI |
//--------------------------------------------------------------------------------- |
char InitLibGUI() |
{ |
font_t *font; |
//--------------------------------------------------------------------------------- |
//---------------------------platform depended part of code------------------------ |
//--------------------------------------------------------------------------------- |
//set new events mask |
gui_ksys_set_events_mask(119); |
//set scan codes input mode for keyboard |
gui_ksys_set_keyboard_input_mode(1); |
//------------------------------------------------------------------------------------ |
FontsMeneger.fnt_fd=(DWORD*)NULL; |
FontsMeneger.fnt_bk=(DWORD*)NULL; |
FontsMeneger.number_fonts=0; |
//load default fonts |
font=LoadFont("CHAR.MT"); |
if (font==NULL) return (TRUE); |
else FontsMeneger.default_font=(DWORD*)font; |
font->flags=font->flags | FONT_FLAG_DEFAULT_FONT_ON; |
return(FALSE); |
} |
//--------------------------------------------------------------------------------- |
// quit from libGUI loop and destroy all GUI objects |
//--------------------------------------------------------------------------------- |
void QuitLibGUI(parent_t *window) |
{ |
font_t *font,*seek_font,*exchange_font; |
gui_timer_t *seek_timer,*exchange_timer; |
gui_message_t message; |
#ifdef DEBUG |
printf("\nbegin free libGUI..."); |
#endif |
//destroy controls of parent window |
message.type=MESSAGE_DESTROY_CONTROL; |
SendMessage((header_t*)window,&message); |
#ifdef DEBUG |
printf("\ncontrols destroyed"); |
#endif |
//destroy timers for callback functions |
seek_timer=(gui_timer_t*)window->timer_bk; |
while(seek_timer!=(gui_timer_t*)NULL) |
{ |
exchange_timer=(gui_timer_t*)seek_timer->tmr_fd; |
DestroyTimerCallbackForFunction(seek_timer); |
seek_timer=exchange_timer; |
} |
#ifdef DEBUG |
printf("\ntimers destroyed"); |
#endif |
//free arrays of parent window |
free(window->message); |
free(window->control_for_callback_function); |
free(window->callback_for_control_callback); |
#ifdef DEBUG |
printf("\narrays destroyed"); |
#endif |
//destroy parent window |
free(window); |
#ifdef DEBUG |
printf("\nparent window destroyed"); |
#endif |
//destroy fonts cash |
seek_font=(font_t*)FontsMeneger.fnt_bk; |
while(seek_font!=(font_t*)NULL) |
{ |
exchange_font=(font_t*)seek_font->fnt_fd; |
free(seek_font->font); |
DestroyFont(seek_font); |
seek_font=exchange_font; |
} |
#ifdef DEBUG |
printf("\nfonts destroyed"); |
printf("\nexit program..."); |
#endif |
exit(0); |
} |
DWORD LibGUIversion(void) |
{ //25.10.09 |
return(91025); |
} |
/programs/develop/libraries/libGUI/SRC/main_libGUI.inc |
---|
0,0 → 1,233 |
/* |
main meneger loop libGUI library |
*/ |
void LibGUImain(parent_t *WindowParent) |
{ |
DWORD event,key,value; |
header_t *control; |
gui_message_t *events_message; |
gui_timer_t *seek_timer,*exchange_timer; |
gui_callbackevent_t *seek_calev,*calev,*exchange_calev; |
int i; |
char quit; |
events_message=(struct MESSAGE*)WindowParent->message; |
//tell all child controls of main parent who is main parent |
events_message->type=MESSAGE_SET_MAIN_PARENT; |
events_message->arg1=(DWORD)WindowParent; |
SendMessage((struct HEADER *)WindowParent,events_message); |
//display all created controls in window |
gui_draw_window(WindowParent); |
events_message->type=MESSAGE_FULL_REDRAW_ALL; |
SendMessage((struct HEADER *)WindowParent,events_message); |
events_message->type=0; |
quit=FALSE; |
WindowParent->number_callbacks=0; |
while (quit==FALSE) |
{ |
//check for timers |
if ((WindowParent->timer_bk!=(DWORD*)NULL) || |
(WindowParent->number_timers_for_controls!=0)) {event=gui_ksys_wait_event_with_timeout(1);} |
else {event=gui_ksys_wait_event();} |
//get and chack system events |
switch(event) |
{ |
case KOLIBRIOS_SYS_EVENT_BUTTON_PRESSED: |
{ |
if (ControlCheckCallbackEvent(WindowParent,DELETE_EVENT)!=NULL) |
{ |
WindowParent->flags |= FLAG_CONNECT_EVENT_ON; |
WindowParent->control_for_callback_function[WindowParent->number_callbacks]= |
(DWORD*)WindowParent; |
WindowParent->callback_for_control_callback[WindowParent->number_callbacks]= |
(DWORD*)ControlCheckCallbackEvent(WindowParent,(DWORD)DELETE_EVENT); |
WindowParent->number_callbacks++; |
} |
quit=TRUE; |
break; |
} |
case KOLIBRIOS_SYS_EVENT_REDRAW: |
{ |
GetNewWindowSizePos(WindowParent); |
SetWindowSizeRequest(WindowParent,WindowParent->ctrl_sizex,WindowParent->ctrl_sizey); |
gui_draw_window(WindowParent); |
events_message->type=MESSAGE_FULL_REDRAW_ALL; |
SendMessage((struct HEADER *)WindowParent,events_message); |
break; |
} |
case KOLIBRIOS_SYS_EVENT_KEYS: |
{ |
key=gui_ksys_get_key(); |
key=key>>8; |
if (key & 128) |
{ |
events_message->arg1=KEY_UP; |
events_message->arg2=key & 127; |
} |
else |
{ |
events_message->arg1=KEY_DOWN; |
events_message->arg2=key; |
} |
events_message->type=MESSAGE_KEYS_EVENT; |
SendMessage((struct HEADER *)WindowParent,events_message); |
break; |
} |
case KOLIBRIOS_SYS_EVENT_MOUSE: |
{ |
value=gui_ksys_get_window_mouse_coordinates(); |
events_message->type=MESSAGE_MOUSE_EVENT; |
events_message->arg2=(value & 0xffff)-screen.y;//y |
value=value >>16; |
events_message->arg1=value-screen.x;//x |
value=gui_ksys_get_mouse_buttons_state(); |
switch(value) |
{ |
case KOLIBRIOS_SYS_MOUSE_BUTTON_LEFT_DOWN: |
{ |
events_message->arg3=MOUSE_LEFT_BUTTON_DOWN; |
break; |
} |
case KOLIBRIOS_SYS_MOUSE_BUTTON_RIGHT_DOWN: |
{ |
events_message->arg3=MOUSE_RIGHT_BUTTON_DOWN; |
break; |
} |
case KOLIBRIOS_SYS_MOUSE_BUTTON_MIDDLE_DOWN: |
{ |
events_message->arg3=MOUSE_MIDDLE_BUTTON_DOWN; |
break; |
} |
case KOLIBRIOS_SYS_MOUSE_BUTTON_4_DOWN: |
{ |
events_message->arg3=MOUSE_4_BUTTON_DOWN; |
break; |
} |
case KOLIBRIOS_SYS_MOUSE_BUTTON_5_DOWN: |
{ |
events_message->arg3=MOUSE_5_BUTTON_DOWN; |
break; |
} |
default: |
{ |
if (events_message->arg3==MOUSE_LEFT_BUTTON_DOWN) |
{ |
events_message->arg3=MOUSE_LEFT_BUTTON_UP; |
break; |
} |
if (events_message->arg3==MOUSE_RIGHT_BUTTON_DOWN) |
{ |
events_message->arg3=MOUSE_RIGHT_BUTTON_UP; |
break; |
} |
if (events_message->arg3==MOUSE_MIDDLE_BUTTON_DOWN) |
{ |
events_message->arg3=MOUSE_MIDDLE_BUTTON_UP; |
break; |
} |
if (events_message->arg3==MOUSE_4_BUTTON_DOWN) |
{ |
events_message->arg3=MOUSE_4_BUTTON_UP; |
break; |
} |
if (events_message->arg3==MOUSE_5_BUTTON_DOWN) |
{ |
events_message->arg3=MOUSE_5_BUTTON_UP; |
break; |
} |
break; |
} |
} |
SendMessage((struct HEADER *)WindowParent,events_message); |
break; |
} |
} |
//call functions for events |
seek_calev=(struct CALLBACKEVENT*)WindowParent->calev_bk; |
while(seek_calev!=(struct CALLBACKEVENT*)NULL) |
{ |
if (seek_calev->event_type==events_message->type) |
{ |
CallbackFunctionForEvent=(void(*)(struct MESSAGE *message,void *data))seek_calev->func; |
CallbackFunctionForEvent(events_message,seek_calev->func_data); |
} |
exchange_calev=(struct CALLBACKEVENT*)seek_calev->calev_fd; |
seek_calev=exchange_calev; |
} |
//call timers of controls |
if (WindowParent->number_timers_for_controls!=0) |
{ |
events_message->type=(char)MESSAGE_CALL_TIMER_EVENT; |
SendMessage((struct HEADER *)WindowParent,events_message); |
} |
//call callback functions |
for(i=0;i<WindowParent->number_callbacks;i++) |
{ |
control=(struct HEADER*)WindowParent->control_for_callback_function[i]; |
//check callback control |
if (control!=(header_t*)NULL) |
{ |
if (control->flags & FLAG_CONNECT_EVENT_ON) |
{ |
calev=(struct CALLBACKEVENT*) |
WindowParent->callback_for_control_callback[i]; |
#ifdef DEBUG |
printf("\ntry to call callback %d for function %d data %d", |
(DWORD)calev, |
(DWORD)calev->func, |
(DWORD)calev->func_data); |
#endif |
CallbackFunction=(void (*)(header_t *Control,void *data))calev->func; |
CallbackFunction(control,calev->func_data); |
control->flags=control->flags & FLAG_CONNECT_EVENT_OFF; |
} |
} |
} |
WindowParent->number_callbacks=0; |
//call timers of parent window |
seek_timer=(struct TIMER*)WindowParent->timer_bk; |
while(seek_timer!=(struct TIMER*)NULL) |
{ |
if (seek_timer->flags & FLAG_TIMER_ON) Timer(seek_timer); |
exchange_timer=(struct TIMER*)seek_timer->tmr_fd; |
seek_timer=exchange_timer; |
} |
//check for IDL function and call it if enabled |
if (WindowParent->IDL_func!=(DWORD*)NULL) |
{ |
IDL_Function=(void(*)(void *data))WindowParent->IDL_func; |
IDL_Function(WindowParent->IDL_func_data); |
} |
} |
} |
/programs/develop/libraries/libGUI/SRC/malloc.inc |
---|
0,0 → 1,3994 |
/* |
This is a version (aka dlmalloc) of malloc/free/realloc written by |
Doug Lea and released to the public domain, as explained at |
http://creativecommons.org/licenses/publicdomain. Send questions, |
comments, complaints, performance data, etc to dl@cs.oswego.edu |
* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) |
Note: There may be an updated version of this malloc obtainable at |
ftp://gee.cs.oswego.edu/pub/misc/malloc.c |
Check before installing! |
* Quickstart |
This library is all in one file to simplify the most common usage: |
ftp it, compile it (-O3), and link it into another program. All of |
the compile-time options default to reasonable values for use on |
most platforms. You might later want to step through various |
compile-time and dynamic tuning options. |
For convenience, an include file for code using this malloc is at: |
ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h |
You don't really need this .h file unless you call functions not |
defined in your system include files. The .h file contains only the |
excerpts from this file needed for using this malloc on ANSI C/C++ |
systems, so long as you haven't changed compile-time options about |
naming and tuning parameters. If you do, then you can create your |
own malloc.h that does include all settings by cutting at the point |
indicated below. Note that you may already by default be using a C |
library containing a malloc that is based on some version of this |
malloc (for example in linux). You might still want to use the one |
in this file to customize settings or to avoid overheads associated |
with library versions. |
* Vital statistics: |
Supported pointer/size_t representation: 4 or 8 bytes |
size_t MUST be an unsigned type of the same width as |
pointers. (If you are using an ancient system that declares |
size_t as a signed type, or need it to be a different width |
than pointers, you can use a previous release of this malloc |
(e.g. 2.7.2) supporting these.) |
Alignment: 8 bytes (default) |
This suffices for nearly all current machines and C compilers. |
However, you can define MALLOC_ALIGNMENT to be wider than this |
if necessary (up to 128bytes), at the expense of using more space. |
Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) |
8 or 16 bytes (if 8byte sizes) |
Each malloced chunk has a hidden word of overhead holding size |
and status information, and additional cross-check word |
if FOOTERS is defined. |
Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) |
8-byte ptrs: 32 bytes (including overhead) |
Even a request for zero bytes (i.e., malloc(0)) returns a |
pointer to something of the minimum allocatable size. |
The maximum overhead wastage (i.e., number of extra bytes |
allocated than were requested in malloc) is less than or equal |
to the minimum size, except for requests >= mmap_threshold that |
are serviced via mmap(), where the worst case wastage is about |
32 bytes plus the remainder from a system page (the minimal |
mmap unit); typically 4096 or 8192 bytes. |
Security: static-safe; optionally more or less |
The "security" of malloc refers to the ability of malicious |
code to accentuate the effects of errors (for example, freeing |
space that is not currently malloc'ed or overwriting past the |
ends of chunks) in code that calls malloc. This malloc |
guarantees not to modify any memory locations below the base of |
heap, i.e., static variables, even in the presence of usage |
errors. The routines additionally detect most improper frees |
and reallocs. All this holds as long as the static bookkeeping |
for malloc itself is not corrupted by some other means. This |
is only one aspect of security -- these checks do not, and |
cannot, detect all possible programming errors. |
If FOOTERS is defined nonzero, then each allocated chunk |
carries an additional check word to verify that it was malloced |
from its space. These check words are the same within each |
execution of a program using malloc, but differ across |
executions, so externally crafted fake chunks cannot be |
freed. This improves security by rejecting frees/reallocs that |
could corrupt heap memory, in addition to the checks preventing |
writes to statics that are always on. This may further improve |
security at the expense of time and space overhead. (Note that |
FOOTERS may also be worth using with MSPACES.) |
By default detected errors cause the program to abort (calling |
"abort()"). You can override this to instead proceed past |
errors by defining PROCEED_ON_ERROR. In this case, a bad free |
has no effect, and a malloc that encounters a bad address |
caused by user overwrites will ignore the bad address by |
dropping pointers and indices to all known memory. This may |
be appropriate for programs that should continue if at all |
possible in the face of programming errors, although they may |
run out of memory because dropped memory is never reclaimed. |
If you don't like either of these options, you can define |
CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything |
else. And if if you are sure that your program using malloc has |
no errors or vulnerabilities, you can define INSECURE to 1, |
which might (or might not) provide a small performance improvement. |
Thread-safety: NOT thread-safe unless USE_LOCKS defined |
When USE_LOCKS is defined, each public call to malloc, free, |
etc is surrounded with either a pthread mutex or a win32 |
spinlock (depending on WIN32). This is not especially fast, and |
can be a major bottleneck. It is designed only to provide |
minimal protection in concurrent environments, and to provide a |
basis for extensions. If you are using malloc in a concurrent |
program, consider instead using ptmalloc, which is derived from |
a version of this malloc. (See http://www.malloc.de). |
System requirements: Any combination of MORECORE and/or MMAP/MUNMAP |
This malloc can use unix sbrk or any emulation (invoked using |
the CALL_MORECORE macro) and/or mmap/munmap or any emulation |
(invoked using CALL_MMAP/CALL_MUNMAP) to get and release system |
memory. On most unix systems, it tends to work best if both |
MORECORE and MMAP are enabled. On Win32, it uses emulations |
based on VirtualAlloc. It also uses common C library functions |
like memset. |
Compliance: I believe it is compliant with the Single Unix Specification |
(See http://www.unix.org). Also SVID/XPG, ANSI C, and probably |
others as well. |
* Overview of algorithms |
This is not the fastest, most space-conserving, most portable, or |
most tunable malloc ever written. However it is among the fastest |
while also being among the most space-conserving, portable and |
tunable. Consistent balance across these factors results in a good |
general-purpose allocator for malloc-intensive programs. |
In most ways, this malloc is a best-fit allocator. Generally, it |
chooses the best-fitting existing chunk for a request, with ties |
broken in approximately least-recently-used order. (This strategy |
normally maintains low fragmentation.) However, for requests less |
than 256bytes, it deviates from best-fit when there is not an |
exactly fitting available chunk by preferring to use space adjacent |
to that used for the previous small request, as well as by breaking |
ties in approximately most-recently-used order. (These enhance |
locality of series of small allocations.) And for very large requests |
(>= 256Kb by default), it relies on system memory mapping |
facilities, if supported. (This helps avoid carrying around and |
possibly fragmenting memory used only for large chunks.) |
All operations (except malloc_stats and mallinfo) have execution |
times that are bounded by a constant factor of the number of bits in |
a size_t, not counting any clearing in calloc or copying in realloc, |
or actions surrounding MORECORE and MMAP that have times |
proportional to the number of non-contiguous regions returned by |
system allocation routines, which is often just 1. |
The implementation is not very modular and seriously overuses |
macros. Perhaps someday all C compilers will do as good a job |
inlining modular code as can now be done by brute-force expansion, |
but now, enough of them seem not to. |
Some compilers issue a lot of warnings about code that is |
dead/unreachable only on some platforms, and also about intentional |
uses of negation on unsigned types. All known cases of each can be |
ignored. |
For a longer but out of date high-level description, see |
http://gee.cs.oswego.edu/dl/html/malloc.html |
* MSPACES |
If MSPACES is defined, then in addition to malloc, free, etc., |
this file also defines mspace_malloc, mspace_free, etc. These |
are versions of malloc routines that take an "mspace" argument |
obtained using create_mspace, to control all internal bookkeeping. |
If ONLY_MSPACES is defined, only these versions are compiled. |
So if you would like to use this allocator for only some allocations, |
and your system malloc for others, you can compile with |
ONLY_MSPACES and then do something like... |
static mspace mymspace = create_mspace(0,0); // for example |
#define mymalloc(bytes) mspace_malloc(mymspace, bytes) |
(Note: If you only need one instance of an mspace, you can instead |
use "USE_DL_PREFIX" to relabel the global malloc.) |
You can similarly create thread-local allocators by storing |
mspaces as thread-locals. For example: |
static __thread mspace tlms = 0; |
void* tlmalloc(size_t bytes) { |
if (tlms == 0) tlms = create_mspace(0, 0); |
return mspace_malloc(tlms, bytes); |
} |
void tlfree(void* mem) { mspace_free(tlms, mem); } |
Unless FOOTERS is defined, each mspace is completely independent. |
You cannot allocate from one and free to another (although |
conformance is only weakly checked, so usage errors are not always |
caught). If FOOTERS is defined, then each chunk carries around a tag |
indicating its originating mspace, and frees are directed to their |
originating spaces. |
------------------------- Compile-time options --------------------------- |
Be careful in setting #define values for numerical constants of type |
size_t. On some systems, literal values are not automatically extended |
to size_t precision unless they are explicitly casted. |
WIN32 default: defined if _WIN32 defined |
Defining WIN32 sets up defaults for MS environment and compilers. |
Otherwise defaults are for unix. |
MALLOC_ALIGNMENT default: (size_t)8 |
Controls the minimum alignment for malloc'ed chunks. It must be a |
power of two and at least 8, even on machines for which smaller |
alignments would suffice. It may be defined as larger than this |
though. Note however that code and data structures are optimized for |
the case of 8-byte alignment. |
MSPACES default: 0 (false) |
If true, compile in support for independent allocation spaces. |
This is only supported if HAVE_MMAP is true. |
ONLY_MSPACES default: 0 (false) |
If true, only compile in mspace versions, not regular versions. |
USE_LOCKS default: 0 (false) |
Causes each call to each public routine to be surrounded with |
pthread or WIN32 mutex lock/unlock. (If set true, this can be |
overridden on a per-mspace basis for mspace versions.) |
FOOTERS default: 0 |
If true, provide extra checking and dispatching by placing |
information in the footers of allocated chunks. This adds |
space and time overhead. |
INSECURE default: 0 |
If true, omit checks for usage errors and heap space overwrites. |
USE_DL_PREFIX default: NOT defined |
Causes compiler to prefix all public routines with the string 'dl'. |
This can be useful when you only want to use this malloc in one part |
of a program, using your regular system malloc elsewhere. |
ABORT default: defined as abort() |
Defines how to abort on failed checks. On most systems, a failed |
check cannot die with an "assert" or even print an informative |
message, because the underlying print routines in turn call malloc, |
which will fail again. Generally, the best policy is to simply call |
abort(). It's not very useful to do more than this because many |
errors due to overwriting will show up as address faults (null, odd |
addresses etc) rather than malloc-triggered checks, so will also |
abort. Also, most compilers know that abort() does not return, so |
can better optimize code conditionally calling it. |
PROCEED_ON_ERROR default: defined as 0 (false) |
Controls whether detected bad addresses cause them to bypassed |
rather than aborting. If set, detected bad arguments to free and |
realloc are ignored. And all bookkeeping information is zeroed out |
upon a detected overwrite of freed heap space, thus losing the |
ability to ever return it from malloc again, but enabling the |
application to proceed. If PROCEED_ON_ERROR is defined, the |
static variable malloc_corruption_error_count is compiled in |
and can be examined to see if errors have occurred. This option |
generates slower code than the default abort policy. |
DEBUG default: NOT defined |
The DEBUG setting is mainly intended for people trying to modify |
this code or diagnose problems when porting to new platforms. |
However, it may also be able to better isolate user errors than just |
using runtime checks. The assertions in the check routines spell |
out in more detail the assumptions and invariants underlying the |
algorithms. The checking is fairly extensive, and will slow down |
execution noticeably. Calling malloc_stats or mallinfo with DEBUG |
set will attempt to check every non-mmapped allocated and free chunk |
in the course of computing the summaries. |
ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) |
Debugging assertion failures can be nearly impossible if your |
version of the assert macro causes malloc to be called, which will |
lead to a cascade of further failures, blowing the runtime stack. |
ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), |
which will usually make debugging easier. |
MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 |
The action to take before "return 0" when malloc fails to be able to |
return memory because there is none available. |
HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES |
True if this system supports sbrk or an emulation of it. |
MORECORE default: sbrk |
The name of the sbrk-style system routine to call to obtain more |
memory. See below for guidance on writing custom MORECORE |
functions. The type of the argument to sbrk/MORECORE varies across |
systems. It cannot be size_t, because it supports negative |
arguments, so it is normally the signed type of the same width as |
size_t (sometimes declared as "intptr_t"). It doesn't much matter |
though. Internally, we only call it with arguments less than half |
the max value of a size_t, which should work across all reasonable |
possibilities, although sometimes generating compiler warnings. See |
near the end of this file for guidelines for creating a custom |
version of MORECORE. |
MORECORE_CONTIGUOUS default: 1 (true) |
If true, take advantage of fact that consecutive calls to MORECORE |
with positive arguments always return contiguous increasing |
addresses. This is true of unix sbrk. It does not hurt too much to |
set it true anyway, since malloc copes with non-contiguities. |
Setting it false when definitely non-contiguous saves time |
and possibly wasted space it would take to discover this though. |
MORECORE_CANNOT_TRIM default: NOT defined |
True if MORECORE cannot release space back to the system when given |
negative arguments. This is generally necessary only if you are |
using a hand-crafted MORECORE function that cannot handle negative |
arguments. |
HAVE_MMAP default: 1 (true) |
True if this system supports mmap or an emulation of it. If so, and |
HAVE_MORECORE is not true, MMAP is used for all system |
allocation. If set and HAVE_MORECORE is true as well, MMAP is |
primarily used to directly allocate very large blocks. It is also |
used as a backup strategy in cases where MORECORE fails to provide |
space from system. Note: A single call to MUNMAP is assumed to be |
able to unmap memory that may have be allocated using multiple calls |
to MMAP, so long as they are adjacent. |
HAVE_MREMAP default: 1 on linux, else 0 |
If true realloc() uses mremap() to re-allocate large blocks and |
extend or shrink allocation spaces. |
MMAP_CLEARS default: 1 on unix |
True if mmap clears memory so calloc doesn't need to. This is true |
for standard unix mmap using /dev/zero. |
USE_BUILTIN_FFS default: 0 (i.e., not used) |
Causes malloc to use the builtin ffs() function to compute indices. |
Some compilers may recognize and intrinsify ffs to be faster than the |
supplied C version. Also, the case of x86 using gcc is special-cased |
to an asm instruction, so is already as fast as it can be, and so |
this setting has no effect. (On most x86s, the asm version is only |
slightly faster than the C version.) |
malloc_getpagesize default: derive from system includes, or 4096. |
The system page size. To the extent possible, this malloc manages |
memory from the system in page-size units. This may be (and |
usually is) a function rather than a constant. This is ignored |
if WIN32, where page size is determined using getSystemInfo during |
initialization. |
USE_DEV_RANDOM default: 0 (i.e., not used) |
Causes malloc to use /dev/random to initialize secure magic seed for |
stamping footers. Otherwise, the current time is used. |
NO_MALLINFO default: 0 |
If defined, don't compile "mallinfo". This can be a simple way |
of dealing with mismatches between system declarations and |
those in this file. |
MALLINFO_FIELD_TYPE default: size_t |
The type of the fields in the mallinfo struct. This was originally |
defined as "int" in SVID etc, but is more usefully defined as |
size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set |
REALLOC_ZERO_BYTES_FREES default: not defined |
This should be set if a call to realloc with zero bytes should |
be the same as a call to free. Some people think it should. Otherwise, |
since this malloc returns a unique pointer for malloc(0), so does |
realloc(p, 0). |
LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H |
LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H |
LACKS_STDLIB_H default: NOT defined unless on WIN32 |
Define these if your system does not have these header files. |
You might need to manually insert some of the declarations they provide. |
DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, |
system_info.dwAllocationGranularity in WIN32, |
otherwise 64K. |
Also settable using mallopt(M_GRANULARITY, x) |
The unit for allocating and deallocating memory from the system. On |
most systems with contiguous MORECORE, there is no reason to |
make this more than a page. However, systems with MMAP tend to |
either require or encourage larger granularities. You can increase |
this value to prevent system allocation functions to be called so |
often, especially if they are slow. The value must be at least one |
page and must be a power of two. Setting to 0 causes initialization |
to either page size or win32 region size. (Note: In previous |
versions of malloc, the equivalent of this option was called |
"TOP_PAD") |
DEFAULT_TRIM_THRESHOLD default: 2MB |
Also settable using mallopt(M_TRIM_THRESHOLD, x) |
The maximum amount of unused top-most memory to keep before |
releasing via malloc_trim in free(). Automatic trimming is mainly |
useful in long-lived programs using contiguous MORECORE. Because |
trimming via sbrk can be slow on some systems, and can sometimes be |
wasteful (in cases where programs immediately afterward allocate |
more large chunks) the value should be high enough so that your |
overall system performance would improve by releasing this much |
memory. As a rough guide, you might set to a value close to the |
average size of a process (program) running on your system. |
Releasing this much memory would allow such a process to run in |
memory. Generally, it is worth tuning trim thresholds when a |
program undergoes phases where several large chunks are allocated |
and released in ways that can reuse each other's storage, perhaps |
mixed with phases where there are no such chunks at all. The trim |
value must be greater than page size to have any useful effect. To |
disable trimming completely, you can set to MAX_SIZE_T. Note that the trick |
some people use of mallocing a huge space and then freeing it at |
program startup, in an attempt to reserve system memory, doesn't |
have the intended effect under automatic trimming, since that memory |
will immediately be returned to the system. |
DEFAULT_MMAP_THRESHOLD default: 256K |
Also settable using mallopt(M_MMAP_THRESHOLD, x) |
The request size threshold for using MMAP to directly service a |
request. Requests of at least this size that cannot be allocated |
using already-existing space will be serviced via mmap. (If enough |
normal freed space already exists it is used instead.) Using mmap |
segregates relatively large chunks of memory so that they can be |
individually obtained and released from the host system. A request |
serviced through mmap is never reused by any other request (at least |
not directly; the system may just so happen to remap successive |
requests to the same locations). Segregating space in this way has |
the benefits that: Mmapped space can always be individually released |
back to the system, which helps keep the system level memory demands |
of a long-lived program low. Also, mapped memory doesn't become |
`locked' between other chunks, as can happen with normally allocated |
chunks, which means that even trimming via malloc_trim would not |
release them. However, it has the disadvantage that the space |
cannot be reclaimed, consolidated, and then used to service later |
requests, as happens with normal chunks. The advantages of mmap |
nearly always outweigh disadvantages for "large" chunks, but the |
value of "large" may vary across systems. The default is an |
empirically derived value that works well in most systems. You can |
disable mmap by setting to MAX_SIZE_T. |
*/ |
//typedef unsigned int size_t; |
#define MALLOC_ALIGNMENT ((size_t)8U) |
#define DEFAULT_MMAP_THRESHOLD ((size_t)32U * (size_t)1024U) |
#define NO_MALLINFO 1 |
#define HAVE_MMAP 1 |
#define MORECORE_CANNOT_TRIM |
#define FOOTERS 0 |
#define ABORT |
//#ifndef WIN32 |
//#ifdef _WIN32 |
//#define WIN32 1 |
//#endif /* _WIN32 */ |
//#endif /* WIN32 */ |
//#ifdef WIN32 |
//#define WIN32_LEAN_AND_MEAN |
//#include <windows.h> |
//#endif /* WIN32 */ |
//default settings for compilation for KolibriOS |
#define HAVE_MMAP 1 |
#define HAVE_MORECORE 0 |
#define LACKS_UNISTD_H |
#define LACKS_SYS_PARAM_H |
#define LACKS_SYS_MMAN_H |
#define LACKS_STRING_H |
#define LACKS_STRINGS_H |
#define LACKS_SYS_TYPES_H |
#define LACKS_STDLIB_H |
#define LACKS_ERRNO_H |
#define LACKS_FCNTL_H |
#define MALLOC_FAILURE_ACTION |
#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */ |
//#endif /* WIN32 */ |
//#if defined(DARWIN) || defined(_DARWIN) |
/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ |
//#ifndef HAVE_MORECORE |
//#define HAVE_MORECORE 0 |
//#define HAVE_MMAP 1 |
//#endif /* HAVE_MORECORE */ |
//#endif /* DARWIN */ |
#ifndef LACKS_SYS_TYPES_H |
#include <sys/types.h> /* For size_t */ |
#endif /* LACKS_SYS_TYPES_H */ |
/* The maximum possible size_t value has all bits set */ |
#define MAX_SIZE_T (~(size_t)0) |
#ifndef ONLY_MSPACES |
#define ONLY_MSPACES 0 |
#endif /* ONLY_MSPACES */ |
#ifndef MSPACES |
#if ONLY_MSPACES |
#define MSPACES 1 |
#else /* ONLY_MSPACES */ |
#define MSPACES 0 |
#endif /* ONLY_MSPACES */ |
#endif /* MSPACES */ |
#ifndef MALLOC_ALIGNMENT |
#define MALLOC_ALIGNMENT ((size_t)8U) |
#endif /* MALLOC_ALIGNMENT */ |
#ifndef FOOTERS |
#define FOOTERS 0 |
#endif /* FOOTERS */ |
#ifndef ABORT |
#define ABORT abort() |
#endif /* ABORT */ |
#ifndef ABORT_ON_ASSERT_FAILURE |
#define ABORT_ON_ASSERT_FAILURE 1 |
#endif /* ABORT_ON_ASSERT_FAILURE */ |
#ifndef PROCEED_ON_ERROR |
#define PROCEED_ON_ERROR 0 |
#endif /* PROCEED_ON_ERROR */ |
#ifndef USE_LOCKS |
#define USE_LOCKS 0 |
#endif /* USE_LOCKS */ |
#ifndef INSECURE |
#define INSECURE 0 |
#endif /* INSECURE */ |
#ifndef HAVE_MMAP |
#define HAVE_MMAP 1 |
#endif /* HAVE_MMAP */ |
#ifndef MMAP_CLEARS |
#define MMAP_CLEARS 1 |
#endif /* MMAP_CLEARS */ |
//#ifndef HAVE_MREMAP |
//#ifdef linux |
//#define HAVE_MREMAP 1 |
//#else /* linux */ |
//#define HAVE_MREMAP 0 |
//#endif /* linux */ |
//#endif /* HAVE_MREMAP */ |
#ifndef MALLOC_FAILURE_ACTION |
#define MALLOC_FAILURE_ACTION errno = ENOMEM; |
#endif /* MALLOC_FAILURE_ACTION */ |
#ifndef HAVE_MORECORE |
#if ONLY_MSPACES |
#define HAVE_MORECORE 0 |
#else /* ONLY_MSPACES */ |
#define HAVE_MORECORE 1 |
#endif /* ONLY_MSPACES */ |
#endif /* HAVE_MORECORE */ |
#if !HAVE_MORECORE |
#define MORECORE_CONTIGUOUS 0 |
#else /* !HAVE_MORECORE */ |
#ifndef MORECORE |
#define MORECORE sbrk |
#endif /* MORECORE */ |
#ifndef MORECORE_CONTIGUOUS |
#define MORECORE_CONTIGUOUS 1 |
#endif /* MORECORE_CONTIGUOUS */ |
#endif /* HAVE_MORECORE */ |
#ifndef DEFAULT_GRANULARITY |
#if MORECORE_CONTIGUOUS |
#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ |
#else /* MORECORE_CONTIGUOUS */ |
#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) |
#endif /* MORECORE_CONTIGUOUS */ |
#endif /* DEFAULT_GRANULARITY */ |
#ifndef DEFAULT_TRIM_THRESHOLD |
#ifndef MORECORE_CANNOT_TRIM |
#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) |
#else /* MORECORE_CANNOT_TRIM */ |
#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T |
#endif /* MORECORE_CANNOT_TRIM */ |
#endif /* DEFAULT_TRIM_THRESHOLD */ |
#ifndef DEFAULT_MMAP_THRESHOLD |
#if HAVE_MMAP |
#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) |
#else /* HAVE_MMAP */ |
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T |
#endif /* HAVE_MMAP */ |
#endif /* DEFAULT_MMAP_THRESHOLD */ |
#ifndef USE_BUILTIN_FFS |
#define USE_BUILTIN_FFS 0 |
#endif /* USE_BUILTIN_FFS */ |
#ifndef USE_DEV_RANDOM |
#define USE_DEV_RANDOM 0 |
#endif /* USE_DEV_RANDOM */ |
#ifndef NO_MALLINFO |
#define NO_MALLINFO 0 |
#endif /* NO_MALLINFO */ |
#ifndef MALLINFO_FIELD_TYPE |
#define MALLINFO_FIELD_TYPE size_t |
#endif /* MALLINFO_FIELD_TYPE */ |
/* |
mallopt tuning options. SVID/XPG defines four standard parameter |
numbers for mallopt, normally defined in malloc.h. None of these |
are used in this malloc, so setting them has no effect. But this |
malloc does support the following options. |
*/ |
#define M_TRIM_THRESHOLD (-1) |
#define M_GRANULARITY (-2) |
#define M_MMAP_THRESHOLD (-3) |
/* ------------------------ Mallinfo declarations ------------------------ */ |
#if !NO_MALLINFO |
#endif /* NO_MALLINFO */ |
#ifdef __cplusplus |
extern "C" { |
#endif /* __cplusplus */ |
#if !ONLY_MSPACES |
/* ------------------- Declarations of public routines ------------------- */ |
#ifndef USE_DL_PREFIX |
#define dlcalloc calloc |
//#define dlfree free |
//#define dlmalloc malloc |
#define dlmemalign memalign |
#define dlrealloc realloc |
#define dlvalloc valloc |
#define dlpvalloc pvalloc |
#define dlmallinfo mallinfo |
#define dlmallopt mallopt |
#define dlmalloc_trim malloc_trim |
#define dlmalloc_stats malloc_stats |
#define dlmalloc_usable_size malloc_usable_size |
#define dlmalloc_footprint malloc_footprint |
#define dlmalloc_max_footprint malloc_max_footprint |
#define dlindependent_calloc independent_calloc |
#define dlindependent_comalloc independent_comalloc |
#endif /* USE_DL_PREFIX */ |
/* |
malloc(size_t n) |
Returns a pointer to a newly allocated chunk of at least n bytes, or |
null if no space is available, in which case errno is set to ENOMEM |
on ANSI C systems. |
If n is zero, malloc returns a minimum-sized chunk. (The minimum |
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit |
systems.) Note that size_t is an unsigned type, so calls with |
arguments that would be negative if signed are interpreted as |
requests for huge amounts of space, which will often fail. The |
maximum supported value of n differs across systems, but is in all |
cases less than the maximum representable value of a size_t. |
*/ |
static void* dlmalloc(size_t); |
/* |
free(void* p) |
Releases the chunk of memory pointed to by p, that had been previously |
allocated using malloc or a related routine such as realloc. |
It has no effect if p is null. If p was not malloced or already |
freed, free(p) will by default cause the current program to abort. |
*/ |
static void dlfree(void*); |
/* |
calloc(size_t n_elements, size_t element_size); |
Returns a pointer to n_elements * element_size bytes, with all locations |
set to zero. |
*/ |
static void* dlcalloc(size_t, size_t); |
/* |
realloc(void* p, size_t n) |
Returns a pointer to a chunk of size n that contains the same data |
as does chunk p up to the minimum of (n, p's size) bytes, or null |
if no space is available. |
The returned pointer may or may not be the same as p. The algorithm |
prefers extending p in most cases when possible, otherwise it |
employs the equivalent of a malloc-copy-free sequence. |
If p is null, realloc is equivalent to malloc. |
If space is not available, realloc returns null, errno is set (if on |
ANSI) and p is NOT freed. |
if n is for fewer bytes than already held by p, the newly unused |
space is lopped off and freed if possible. realloc with a size |
argument of zero (re)allocates a minimum-sized chunk. |
The old unix realloc convention of allowing the last-free'd chunk |
to be used as an argument to realloc is not supported. |
*/ |
static void* dlrealloc(void*, size_t); |
/* |
memalign(size_t alignment, size_t n); |
Returns a pointer to a newly allocated chunk of n bytes, aligned |
in accord with the alignment argument. |
The alignment argument should be a power of two. If the argument is |
not a power of two, the nearest greater power is used. |
8-byte alignment is guaranteed by normal malloc calls, so don't |
bother calling memalign with an argument of 8 or less. |
Overreliance on memalign is a sure way to fragment space. |
*/ |
static void* dlmemalign(size_t, size_t); |
/* |
valloc(size_t n); |
Equivalent to memalign(pagesize, n), where pagesize is the page |
size of the system. If the pagesize is unknown, 4096 is used. |
*/ |
static void* dlvalloc(size_t); |
/* |
mallopt(int parameter_number, int parameter_value) |
Sets tunable parameters The format is to provide a |
(parameter-number, parameter-value) pair. mallopt then sets the |
corresponding parameter to the argument value if it can (i.e., so |
long as the value is meaningful), and returns 1 if successful else |
0. SVID/XPG/ANSI defines four standard param numbers for mallopt, |
normally defined in malloc.h. None of these are use in this malloc, |
so setting them has no effect. But this malloc also supports other |
options in mallopt. See below for details. Briefly, supported |
parameters are as follows (listed defaults are for "typical" |
configurations). |
Symbol param # default allowed param values |
M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables) |
M_GRANULARITY -2 page size any power of 2 >= page size |
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) |
*/ |
static int dlmallopt(int, int); |
/* |
malloc_footprint(); |
Returns the number of bytes obtained from the system. The total |
number of bytes allocated by malloc, realloc etc., is less than this |
value. Unlike mallinfo, this function returns only a precomputed |
result, so can be called frequently to monitor memory consumption. |
Even if locks are otherwise defined, this function does not use them, |
so results might not be up to date. |
*/ |
static size_t dlmalloc_footprint(void); |
/* |
malloc_max_footprint(); |
Returns the maximum number of bytes obtained from the system. This |
value will be greater than current footprint if deallocated space |
has been reclaimed by the system. The peak number of bytes allocated |
by malloc, realloc etc., is less than this value. Unlike mallinfo, |
this function returns only a precomputed result, so can be called |
frequently to monitor memory consumption. Even if locks are |
otherwise defined, this function does not use them, so results might |
not be up to date. |
*/ |
static size_t dlmalloc_max_footprint(void); |
#if !NO_MALLINFO |
#endif /* NO_MALLINFO */ |
/* |
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); |
independent_calloc is similar to calloc, but instead of returning a |
single cleared space, it returns an array of pointers to n_elements |
independent elements that can hold contents of size elem_size, each |
of which starts out cleared, and can be independently freed, |
realloc'ed etc. The elements are guaranteed to be adjacently |
allocated (this is not guaranteed to occur with multiple callocs or |
mallocs), which may also improve cache locality in some |
applications. |
The "chunks" argument is optional (i.e., may be null, which is |
probably the most typical usage). If it is null, the returned array |
is itself dynamically allocated and should also be freed when it is |
no longer needed. Otherwise, the chunks array must be of at least |
n_elements in length. It is filled in with the pointers to the |
chunks. |
In either case, independent_calloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and "chunks" |
is null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use regular calloc and assign pointers into this |
space to represent elements. (In this case though, you cannot |
independently free elements.) |
independent_calloc simplifies and speeds up implementations of many |
kinds of pools. It may also be useful when constructing large data |
structures that initially have a fixed number of fixed-sized nodes, |
but the number is not known at compile time, and some of the nodes |
may later need to be freed. For example: |
struct Node { int item; struct Node* next; }; |
struct Node* build_list() { |
struct Node** pool; |
int n = read_number_of_nodes_needed(); |
if (n <= 0) return 0; |
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); |
if (pool == 0) die(); |
// organize into a linked list... |
struct Node* first = pool[0]; |
for (i = 0; i < n-1; ++i) |
pool[i]->next = pool[i+1]; |
free(pool); // Can now free the array (or not, if it is needed later) |
return first; |
} |
*/ |
static void** dlindependent_calloc(size_t, size_t, void**); |
/* |
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); |
independent_comalloc allocates, all at once, a set of n_elements |
chunks with sizes indicated in the "sizes" array. It returns |
an array of pointers to these elements, each of which can be |
independently freed, realloc'ed etc. The elements are guaranteed to |
be adjacently allocated (this is not guaranteed to occur with |
multiple callocs or mallocs), which may also improve cache locality |
in some applications. |
The "chunks" argument is optional (i.e., may be null). If it is null |
the returned array is itself dynamically allocated and should also |
be freed when it is no longer needed. Otherwise, the chunks array |
must be of at least n_elements in length. It is filled in with the |
pointers to the chunks. |
In either case, independent_comalloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and chunks is |
null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use a single regular malloc, and assign pointers at |
particular offsets in the aggregate space. (In this case though, you |
cannot independently free elements.) |
independent_comallac differs from independent_calloc in that each |
element may have a different size, and also that it does not |
automatically clear elements. |
independent_comalloc can be used to speed up allocation in cases |
where several structs or objects must always be allocated at the |
same time. For example: |
struct Head { ... } |
struct Foot { ... } |
void send_message(char* msg) { |
int msglen = strlen(msg); |
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; |
void* chunks[3]; |
if (independent_comalloc(3, sizes, chunks) == 0) |
die(); |
struct Head* head = (struct Head*)(chunks[0]); |
char* body = (char*)(chunks[1]); |
struct Foot* foot = (struct Foot*)(chunks[2]); |
// ... |
} |
In general though, independent_comalloc is worth using only for |
larger values of n_elements. For small values, you probably won't |
detect enough difference from series of malloc calls to bother. |
Overuse of independent_comalloc can increase overall memory usage, |
since it cannot reuse existing noncontiguous small chunks that |
might be available for some of the elements. |
*/ |
static void** dlindependent_comalloc(size_t, size_t*, void**); |
/* |
pvalloc(size_t n); |
Equivalent to valloc(minimum-page-that-holds(n)), that is, |
round up n to nearest pagesize. |
*/ |
static void* dlpvalloc(size_t); |
/* |
malloc_trim(size_t pad); |
If possible, gives memory back to the system (via negative arguments |
to sbrk) if there is unused memory at the `high' end of the malloc |
pool or in unused MMAP segments. You can call this after freeing |
large blocks of memory to potentially reduce the system-level memory |
requirements of a program. However, it cannot guarantee to reduce |
memory. Under some allocation patterns, some large free blocks of |
memory will be locked between two used chunks, so they cannot be |
given back to the system. |
The `pad' argument to malloc_trim represents the amount of free |
trailing space to leave untrimmed. If this argument is zero, only |
the minimum amount of memory to maintain internal data structures |
will be left. Non-zero arguments can be supplied to maintain enough |
trailing space to service future expected allocations without having |
to re-obtain memory from the system. |
Malloc_trim returns 1 if it actually released any memory, else 0. |
*/ |
static int dlmalloc_trim(size_t); |
/* |
malloc_usable_size(void* p); |
Returns the number of bytes you can actually use in |
an allocated chunk, which may be more than you requested (although |
often not) due to alignment and minimum size constraints. |
You can use this many bytes without worrying about |
overwriting other allocated objects. This is not a particularly great |
programming practice. malloc_usable_size can be more useful in |
debugging and assertions, for example: |
p = malloc(n); |
assert(malloc_usable_size(p) >= 256); |
*/ |
static size_t dlmalloc_usable_size(void*); |
/* |
malloc_stats(); |
Prints on stderr the amount of space obtained from the system (both |
via sbrk and mmap), the maximum amount (which may be more than |
current if malloc_trim and/or munmap got called), and the current |
number of bytes allocated via malloc (or realloc, etc) but not yet |
freed. Note that this is the number of bytes allocated, not the |
number requested. It will be larger than the number requested |
because of alignment and bookkeeping overhead. Because it includes |
alignment wastage as being in use, this figure may be greater than |
zero even when no user-level chunks are allocated. |
The reported current and maximum system memory can be inaccurate if |
a program makes other calls to system memory allocation functions |
(normally sbrk) outside of malloc. |
malloc_stats prints only the most commonly interesting statistics. |
More information can be obtained by calling mallinfo. |
*/ |
static void dlmalloc_stats(void); |
#endif /* ONLY_MSPACES */ |
////////////////////////////////////////////////////////////////////////// |
// declaration of melloc,free,realloc |
////////////////////////////////////////////////////////////////////////// |
void* malloc(size_t size) |
{ |
void *mem; |
mem=dlmalloc(size); |
if (mem!=0) memset(mem,0,size);//cleare befor use |
return(mem); |
} |
void free(void *mem) |
{ |
dlfree(mem); |
} |
#if MSPACES |
#endif /* MSPACES */ |
#ifdef __cplusplus |
}; /* end of extern "C" */ |
#endif /* __cplusplus */ |
/* |
======================================================================== |
To make a fully customizable malloc.h header file, cut everything |
above this line, put into file malloc.h, edit to suit, and #include it |
on the next line, as well as in programs that use this malloc. |
======================================================================== |
*/ |
/* #include "malloc.h" */ |
/*------------------------------ internal #includes ---------------------- */ |
#ifdef WIN32 |
#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ |
#endif /* WIN32 */ |
//#include <stdio.h> /* for printing in malloc_stats */ |
#ifndef LACKS_ERRNO_H |
#include <errno.h> /* for MALLOC_FAILURE_ACTION */ |
#endif /* LACKS_ERRNO_H */ |
#if FOOTERS |
#include <time.h> /* for magic initialization */ |
#endif /* FOOTERS */ |
#ifndef LACKS_STDLIB_H |
#include <stdlib.h> /* for abort() */ |
#endif /* LACKS_STDLIB_H */ |
//#ifdef DEBUG |
//#if ABORT_ON_ASSERT_FAILURE |
//#define assert(x) if(!(x)) ABORT |
//#else /* ABORT_ON_ASSERT_FAILURE */ |
//#include <assert.h> |
//#endif /* ABORT_ON_ASSERT_FAILURE */ |
//#else /* DEBUG */ |
#define assert(x) |
//#endif /* DEBUG */ |
#ifndef LACKS_STRING_H |
#include <string.h> /* for memset etc */ |
#endif /* LACKS_STRING_H */ |
#if USE_BUILTIN_FFS |
#ifndef LACKS_STRINGS_H |
#include <strings.h> /* for ffs */ |
#endif /* LACKS_STRINGS_H */ |
#endif /* USE_BUILTIN_FFS */ |
#if HAVE_MMAP |
#ifndef LACKS_SYS_MMAN_H |
#include <sys/mman.h> /* for mmap */ |
#endif /* LACKS_SYS_MMAN_H */ |
#ifndef LACKS_FCNTL_H |
#include <fcntl.h> |
#endif /* LACKS_FCNTL_H */ |
#endif /* HAVE_MMAP */ |
#if HAVE_MORECORE |
#endif /* HAVE_MMAP */ |
#ifndef WIN32 |
#endif |
/* ------------------- size_t and alignment properties -------------------- */ |
/* The byte and bit size of a size_t */ |
#define SIZE_T_SIZE (sizeof(size_t)) |
#define SIZE_T_BITSIZE (sizeof(size_t) << 3) |
/* Some constants coerced to size_t */ |
/* Annoying but necessary to avoid errors on some plaftorms */ |
#define SIZE_T_ZERO ((size_t)0) |
#define SIZE_T_ONE ((size_t)1) |
#define SIZE_T_TWO ((size_t)2) |
#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) |
#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) |
#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) |
#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) |
/* The bit mask value corresponding to MALLOC_ALIGNMENT */ |
#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) |
/* True if address a has acceptable alignment */ |
#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) |
/* the number of bytes to offset an address to align it */ |
#define align_offset(A)\ |
((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ |
((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) |
/* -------------------------- MMAP preliminaries ------------------------- */ |
/* |
If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and |
checks to fail so compiler optimizer can delete code rather than |
using so many "#if"s. |
*/ |
/* MORECORE and MMAP must return MFAIL on failure */ |
#define MFAIL ((void*)(MAX_SIZE_T)) |
#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ |
/* HAVE_MMAP */ |
#define IS_MMAPPED_BIT (SIZE_T_ONE) |
#define USE_MMAP_BIT (SIZE_T_ONE) |
//////////////////////////////////////////////////////////////// |
// KolibriOS specifik |
//////////////////////////////////////////////////////////////// |
void* gui_ksys_mem_alloc(size_t size) |
{ |
void *value; |
__asm__ __volatile__( |
"int $0x40" |
:"=a"(value) |
:"a"(68),"b"(12),"c"(size) |
:"memory"); |
return (value != 0)? value: MFAIL; |
} |
int gui_ksys_mem_free(void *mem,size_t size) |
{ |
__asm__ __volatile__( |
"int $0x40" |
: |
:"a"(68),"b"(13),"c"(mem) |
:"memory"); |
return(0); |
} |
//#define gui_ksys_mem_alloc(s) win32mmap(s) |
//#define CALL_MUNMAP(a, s) win32munmap((a), (s)) |
//#define DIRECT_MMAP(s) win32direct_mmap(s) |
#if HAVE_MMAP && HAVE_MREMAP |
#else /* HAVE_MMAP && HAVE_MREMAP */ |
#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL |
#endif /* HAVE_MMAP && HAVE_MREMAP */ |
#if HAVE_MORECORE |
#else /* HAVE_MORECORE */ |
#define CALL_MORECORE(S) MFAIL |
#endif /* HAVE_MORECORE */ |
/* mstate bit set if continguous morecore disabled or failed */ |
#define USE_NONCONTIGUOUS_BIT (4U) |
/* segment bit set in create_mspace_with_base */ |
#define EXTERN_BIT (8U) |
/* --------------------------- Lock preliminaries ------------------------ */ |
#if USE_LOCKS |
#else /* USE_LOCKS */ |
#define USE_LOCK_BIT (0U) |
#define INITIAL_LOCK(l) |
#endif /* USE_LOCKS */ |
#if USE_LOCKS && HAVE_MORECORE |
#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex); |
#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex); |
#else /* USE_LOCKS && HAVE_MORECORE */ |
#define ACQUIRE_MORECORE_LOCK() |
#define RELEASE_MORECORE_LOCK() |
#endif /* USE_LOCKS && HAVE_MORECORE */ |
#if USE_LOCKS |
#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex); |
#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex); |
#else /* USE_LOCKS */ |
#define ACQUIRE_MAGIC_INIT_LOCK() |
#define RELEASE_MAGIC_INIT_LOCK() |
#endif /* USE_LOCKS */ |
/* ----------------------- Chunk representations ------------------------ */ |
/* |
(The following includes lightly edited explanations by Colin Plumb.) |
The malloc_chunk declaration below is misleading (but accurate and |
necessary). It declares a "view" into memory allowing access to |
necessary fields at known offsets from a given base. |
Chunks of memory are maintained using a `boundary tag' method as |
originally described by Knuth. (See the paper by Paul Wilson |
ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such |
techniques.) Sizes of free chunks are stored both in the front of |
each chunk and at the end. This makes consolidating fragmented |
chunks into bigger chunks fast. The head fields also hold bits |
representing whether chunks are free or in use. |
Here are some pictures to make it clearer. They are "exploded" to |
show that the state of a chunk can be thought of as extending from |
the high 31 bits of the head field of its header through the |
prev_foot and PINUSE_BIT bit of the following chunk header. |
A chunk that's in use looks like: |
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Size of previous chunk (if P = 1) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| |
| Size of this chunk 1| +-+ |
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | |
+- -+ |
| | |
+- -+ |
| : |
+- size - sizeof(size_t) available payload bytes -+ |
: | |
chunk-> +- -+ |
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| |
| Size of next chunk (may or may not be in use) | +-+ |
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
And if it's free, it looks like this: |
chunk-> +- -+ |
| User payload (must be in use, or we would have merged!) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| |
| Size of this chunk 0| +-+ |
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Next pointer | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Prev pointer | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| : |
+- size - sizeof(struct chunk) unused bytes -+ |
: | |
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Size of this chunk | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| |
| Size of next chunk (must be in use, or we would have merged)| +-+ |
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| : |
+- User payload -+ |
: | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|0| |
+-+ |
Note that since we always merge adjacent free chunks, the chunks |
adjacent to a free chunk must be in use. |
Given a pointer to a chunk (which can be derived trivially from the |
payload pointer) we can, in O(1) time, find out whether the adjacent |
chunks are free, and if so, unlink them from the lists that they |
are on and merge them with the current chunk. |
Chunks always begin on even word boundaries, so the mem portion |
(which is returned to the user) is also on an even word boundary, and |
thus at least double-word aligned. |
The P (PINUSE_BIT) bit, stored in the unused low-order bit of the |
chunk size (which is always a multiple of two words), is an in-use |
bit for the *previous* chunk. If that bit is *clear*, then the |
word before the current chunk size contains the previous chunk |
size, and can be used to find the front of the previous chunk. |
The very first chunk allocated always has this bit set, preventing |
access to non-existent (or non-owned) memory. If pinuse is set for |
any given chunk, then you CANNOT determine the size of the |
previous chunk, and might even get a memory addressing fault when |
trying to do so. |
The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of |
the chunk size redundantly records whether the current chunk is |
inuse. This redundancy enables usage checks within free and realloc, |
and reduces indirection when freeing and consolidating chunks. |
Each freshly allocated chunk must have both cinuse and pinuse set. |
That is, each allocated chunk borders either a previously allocated |
and still in-use chunk, or the base of its memory arena. This is |
ensured by making all allocations from the the `lowest' part of any |
found chunk. Further, no free chunk physically borders another one, |
so each free chunk is known to be preceded and followed by either |
inuse chunks or the ends of memory. |
Note that the `foot' of the current chunk is actually represented |
as the prev_foot of the NEXT chunk. This makes it easier to |
deal with alignments etc but can be very confusing when trying |
to extend or adapt this code. |
The exceptions to all this are |
1. The special chunk `top' is the top-most available chunk (i.e., |
the one bordering the end of available memory). It is treated |
specially. Top is never included in any bin, is used only if |
no other chunk is available, and is released back to the |
system if it is very large (see M_TRIM_THRESHOLD). In effect, |
the top chunk is treated as larger (and thus less well |
fitting) than any other available chunk. The top chunk |
doesn't update its trailing size field since there is no next |
contiguous chunk that would have to index off it. However, |
space is still allocated for it (TOP_FOOT_SIZE) to enable |
separation or merging when space is extended. |
3. Chunks allocated via mmap, which have the lowest-order bit |
(IS_MMAPPED_BIT) set in their prev_foot fields, and do not set |
PINUSE_BIT in their head fields. Because they are allocated |
one-by-one, each must carry its own prev_foot field, which is |
also used to hold the offset this chunk has within its mmapped |
region, which is needed to preserve alignment. Each mmapped |
chunk is trailed by the first two fields of a fake next-chunk |
for sake of usage checks. |
*/ |
struct malloc_chunk { |
size_t prev_foot; /* Size of previous chunk (if free). */ |
size_t head; /* Size and inuse bits. */ |
struct malloc_chunk* fd; /* double links -- used only if free. */ |
struct malloc_chunk* bk; |
}; |
typedef struct malloc_chunk mchunk; |
typedef struct malloc_chunk* mchunkptr; |
typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ |
typedef unsigned int bindex_t; /* Described below */ |
typedef unsigned int binmap_t; /* Described below */ |
typedef unsigned int flag_t; /* The type of various bit flag sets */ |
/* ------------------- Chunks sizes and alignments ----------------------- */ |
#define MCHUNK_SIZE (sizeof(mchunk)) |
#if FOOTERS |
#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) |
#else /* FOOTERS */ |
#define CHUNK_OVERHEAD (SIZE_T_SIZE) |
#endif /* FOOTERS */ |
/* MMapped chunks need a second word of overhead ... */ |
#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) |
/* ... and additional padding for fake next-chunk at foot */ |
#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) |
/* The smallest size we can malloc is an aligned minimal chunk */ |
#define MIN_CHUNK_SIZE\ |
((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) |
/* conversion from malloc headers to user pointers, and back */ |
#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) |
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) |
/* chunk associated with aligned address A */ |
#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) |
/* Bounds on request (not chunk) sizes. */ |
#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) |
#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) |
/* pad request bytes into a usable size */ |
#define pad_request(req) \ |
(((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) |
/* pad request, checking for minimum (but not maximum) */ |
#define request2size(req) \ |
(((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) |
/* ------------------ Operations on head and foot fields ----------------- */ |
/* |
The head field of a chunk is or'ed with PINUSE_BIT when previous |
adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in |
use. If the chunk was obtained with mmap, the prev_foot field has |
IS_MMAPPED_BIT set, otherwise holding the offset of the base of the |
mmapped region to the base of the chunk. |
*/ |
#define PINUSE_BIT (SIZE_T_ONE) |
#define CINUSE_BIT (SIZE_T_TWO) |
#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) |
/* Head value for fenceposts */ |
#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) |
/* extraction of fields from head words */ |
#define cinuse(p) ((p)->head & CINUSE_BIT) |
#define pinuse(p) ((p)->head & PINUSE_BIT) |
#define chunksize(p) ((p)->head & ~(INUSE_BITS)) |
#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) |
#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT) |
/* Treat space at ptr +/- offset as a chunk */ |
#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) |
#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) |
/* Ptr to next or previous physical malloc_chunk. */ |
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS))) |
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) |
/* extract next chunk's pinuse bit */ |
#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) |
/* Get/set size at footer */ |
#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) |
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) |
/* Set size, pinuse bit, and foot */ |
#define set_size_and_pinuse_of_free_chunk(p, s)\ |
((p)->head = (s|PINUSE_BIT), set_foot(p, s)) |
/* Set size, pinuse bit, foot, and clear next pinuse */ |
#define set_free_with_pinuse(p, s, n)\ |
(clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) |
#define is_mmapped(p)\ |
(!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT)) |
/* Get the internal overhead associated with chunk p */ |
#define overhead_for(p)\ |
(is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) |
/* Return true if malloced space is not necessarily cleared */ |
#if MMAP_CLEARS |
#define calloc_must_clear(p) (!is_mmapped(p)) |
#else /* MMAP_CLEARS */ |
#define calloc_must_clear(p) (1) |
#endif /* MMAP_CLEARS */ |
/* ---------------------- Overlaid data structures ----------------------- */ |
/* |
When chunks are not in use, they are treated as nodes of either |
lists or trees. |
"Small" chunks are stored in circular doubly-linked lists, and look |
like this: |
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Size of previous chunk | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
`head:' | Size of chunk, in bytes |P| |
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Forward pointer to next chunk in list | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Back pointer to previous chunk in list | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Unused space (may be 0 bytes long) . |
. . |
. | |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
`foot:' | Size of chunk, in bytes | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
Larger chunks are kept in a form of bitwise digital trees (aka |
tries) keyed on chunksizes. Because malloc_tree_chunks are only for |
free chunks greater than 256 bytes, their size doesn't impose any |
constraints on user chunk sizes. Each node looks like: |
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Size of previous chunk | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
`head:' | Size of chunk, in bytes |P| |
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Forward pointer to next chunk of same size | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Back pointer to previous chunk of same size | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Pointer to left child (child[0]) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Pointer to right child (child[1]) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Pointer to parent | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| bin index of this chunk | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Unused space . |
. | |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
`foot:' | Size of chunk, in bytes | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
Each tree holding treenodes is a tree of unique chunk sizes. Chunks |
of the same size are arranged in a circularly-linked list, with only |
the oldest chunk (the next to be used, in our FIFO ordering) |
actually in the tree. (Tree members are distinguished by a non-null |
parent pointer.) If a chunk with the same size an an existing node |
is inserted, it is linked off the existing node using pointers that |
work in the same way as fd/bk pointers of small chunks. |
Each tree contains a power of 2 sized range of chunk sizes (the |
smallest is 0x100 <= x < 0x180), which is is divided in half at each |
tree level, with the chunks in the smaller half of the range (0x100 |
<= x < 0x140 for the top nose) in the left subtree and the larger |
half (0x140 <= x < 0x180) in the right subtree. This is, of course, |
done by inspecting individual bits. |
Using these rules, each node's left subtree contains all smaller |
sizes than its right subtree. However, the node at the root of each |
subtree has no particular ordering relationship to either. (The |
dividing line between the subtree sizes is based on trie relation.) |
If we remove the last chunk of a given size from the interior of the |
tree, we need to replace it with a leaf node. The tree ordering |
rules permit a node to be replaced by any leaf below it. |
The smallest chunk in a tree (a common operation in a best-fit |
allocator) can be found by walking a path to the leftmost leaf in |
the tree. Unlike a usual binary tree, where we follow left child |
pointers until we reach a null, here we follow the right child |
pointer any time the left one is null, until we reach a leaf with |
both child pointers null. The smallest chunk in the tree will be |
somewhere along that path. |
The worst case number of steps to add, find, or remove a node is |
bounded by the number of bits differentiating chunks within |
bins. Under current bin calculations, this ranges from 6 up to 21 |
(for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case |
is of course much better. |
*/ |
struct malloc_tree_chunk { |
/* The first four fields must be compatible with malloc_chunk */ |
size_t prev_foot; |
size_t head; |
struct malloc_tree_chunk* fd; |
struct malloc_tree_chunk* bk; |
struct malloc_tree_chunk* child[2]; |
struct malloc_tree_chunk* parent; |
bindex_t index; |
}; |
typedef struct malloc_tree_chunk tchunk; |
typedef struct malloc_tree_chunk* tchunkptr; |
typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ |
/* A little helper macro for trees */ |
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) |
/* ----------------------------- Segments -------------------------------- */ |
/* |
Each malloc space may include non-contiguous segments, held in a |
list headed by an embedded malloc_segment record representing the |
top-most space. Segments also include flags holding properties of |
the space. Large chunks that are directly allocated by mmap are not |
included in this list. They are instead independently created and |
destroyed without otherwise keeping track of them. |
Segment management mainly comes into play for spaces allocated by |
MMAP. Any call to MMAP might or might not return memory that is |
adjacent to an existing segment. MORECORE normally contiguously |
extends the current space, so this space is almost always adjacent, |
which is simpler and faster to deal with. (This is why MORECORE is |
used preferentially to MMAP when both are available -- see |
sys_alloc.) When allocating using MMAP, we don't use any of the |
hinting mechanisms (inconsistently) supported in various |
implementations of unix mmap, or distinguish reserving from |
committing memory. Instead, we just ask for space, and exploit |
contiguity when we get it. It is probably possible to do |
better than this on some systems, but no general scheme seems |
to be significantly better. |
Management entails a simpler variant of the consolidation scheme |
used for chunks to reduce fragmentation -- new adjacent memory is |
normally prepended or appended to an existing segment. However, |
there are limitations compared to chunk consolidation that mostly |
reflect the fact that segment processing is relatively infrequent |
(occurring only when getting memory from system) and that we |
don't expect to have huge numbers of segments: |
* Segments are not indexed, so traversal requires linear scans. (It |
would be possible to index these, but is not worth the extra |
overhead and complexity for most programs on most platforms.) |
* New segments are only appended to old ones when holding top-most |
memory; if they cannot be prepended to others, they are held in |
different segments. |
Except for the top-most segment of an mstate, each segment record |
is kept at the tail of its segment. Segments are added by pushing |
segment records onto the list headed by &mstate.seg for the |
containing mstate. |
Segment flags control allocation/merge/deallocation policies: |
* If EXTERN_BIT set, then we did not allocate this segment, |
and so should not try to deallocate or merge with others. |
(This currently holds only for the initial segment passed |
into create_mspace_with_base.) |
* If IS_MMAPPED_BIT set, the segment may be merged with |
other surrounding mmapped segments and trimmed/de-allocated |
using munmap. |
* If neither bit is set, then the segment was obtained using |
MORECORE so can be merged with surrounding MORECORE'd segments |
and deallocated/trimmed using MORECORE with negative arguments. |
*/ |
struct malloc_segment { |
char* base; /* base address */ |
size_t size; /* allocated size */ |
struct malloc_segment* next; /* ptr to next segment */ |
flag_t sflags; /* mmap and extern flag */ |
}; |
#define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT) |
#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) |
typedef struct malloc_segment msegment; |
typedef struct malloc_segment* msegmentptr; |
/* ---------------------------- malloc_state ----------------------------- */ |
/* |
A malloc_state holds all of the bookkeeping for a space. |
The main fields are: |
Top |
The topmost chunk of the currently active segment. Its size is |
cached in topsize. The actual size of topmost space is |
topsize+TOP_FOOT_SIZE, which includes space reserved for adding |
fenceposts and segment records if necessary when getting more |
space from the system. The size at which to autotrim top is |
cached from mparams in trim_check, except that it is disabled if |
an autotrim fails. |
Designated victim (dv) |
This is the preferred chunk for servicing small requests that |
don't have exact fits. It is normally the chunk split off most |
recently to service another small request. Its size is cached in |
dvsize. The link fields of this chunk are not maintained since it |
is not kept in a bin. |
SmallBins |
An array of bin headers for free chunks. These bins hold chunks |
with sizes less than MIN_LARGE_SIZE bytes. Each bin contains |
chunks of all the same size, spaced 8 bytes apart. To simplify |
use in double-linked lists, each bin header acts as a malloc_chunk |
pointing to the real first node, if it exists (else pointing to |
itself). This avoids special-casing for headers. But to avoid |
waste, we allocate only the fd/bk pointers of bins, and then use |
repositioning tricks to treat these as the fields of a chunk. |
TreeBins |
Treebins are pointers to the roots of trees holding a range of |
sizes. There are 2 equally spaced treebins for each power of two |
from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything |
larger. |
Bin maps |
There is one bit map for small bins ("smallmap") and one for |
treebins ("treemap). Each bin sets its bit when non-empty, and |
clears the bit when empty. Bit operations are then used to avoid |
bin-by-bin searching -- nearly all "search" is done without ever |
looking at bins that won't be selected. The bit maps |
conservatively use 32 bits per map word, even if on 64bit system. |
For a good description of some of the bit-based techniques used |
here, see Henry S. Warren Jr's book "Hacker's Delight" (and |
supplement at http://hackersdelight.org/). Many of these are |
intended to reduce the branchiness of paths through malloc etc, as |
well as to reduce the number of memory locations read or written. |
Segments |
A list of segments headed by an embedded malloc_segment record |
representing the initial space. |
Address check support |
The least_addr field is the least address ever obtained from |
MORECORE or MMAP. Attempted frees and reallocs of any address less |
than this are trapped (unless INSECURE is defined). |
Magic tag |
A cross-check field that should always hold same value as mparams.magic. |
Flags |
Bits recording whether to use MMAP, locks, or contiguous MORECORE |
Statistics |
Each space keeps track of current and maximum system memory |
obtained via MORECORE or MMAP. |
Locking |
If USE_LOCKS is defined, the "mutex" lock is acquired and released |
around every public call using this mspace. |
*/ |
/* Bin types, widths and sizes */ |
#define NSMALLBINS (32U) |
#define NTREEBINS (32U) |
#define SMALLBIN_SHIFT (3U) |
#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) |
#define TREEBIN_SHIFT (8U) |
#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) |
#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) |
#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) |
struct malloc_state { |
binmap_t smallmap; |
binmap_t treemap; |
size_t dvsize; |
size_t topsize; |
char* least_addr; |
mchunkptr dv; |
mchunkptr top; |
size_t trim_check; |
size_t magic; |
mchunkptr smallbins[(NSMALLBINS+1)*2]; |
tbinptr treebins[NTREEBINS]; |
size_t footprint; |
size_t max_footprint; |
flag_t mflags; |
#if USE_LOCKS |
MLOCK_T mutex; /* locate lock among fields that rarely change */ |
#endif /* USE_LOCKS */ |
msegment seg; |
}; |
typedef struct malloc_state* mstate; |
/* ------------- Global malloc_state and malloc_params ------------------- */ |
/* |
malloc_params holds global properties, including those that can be |
dynamically set using mallopt. There is a single instance, mparams, |
initialized in init_mparams. |
*/ |
struct malloc_params { |
size_t magic; |
size_t page_size; |
size_t granularity; |
size_t mmap_threshold; |
size_t trim_threshold; |
flag_t default_mflags; |
}; |
static struct malloc_params mparams; |
/* The global malloc_state used for all non-"mspace" calls */ |
static struct malloc_state _gm_; |
#define gm (&_gm_) |
#define is_global(M) ((M) == &_gm_) |
#define is_initialized(M) ((M)->top != 0) |
/* -------------------------- system alloc setup ------------------------- */ |
/* Operations on mflags */ |
#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) |
#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) |
#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) |
#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) |
#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) |
#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) |
#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) |
#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) |
#define set_lock(M,L)\ |
((M)->mflags = (L)?\ |
((M)->mflags | USE_LOCK_BIT) :\ |
((M)->mflags & ~USE_LOCK_BIT)) |
/* page-align a size */ |
#define page_align(S)\ |
(((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE)) |
/* granularity-align a size */ |
#define granularity_align(S)\ |
(((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE)) |
#define is_page_aligned(S)\ |
(((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) |
#define is_granularity_aligned(S)\ |
(((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) |
/* True if segment S holds address A */ |
#define segment_holds(S, A)\ |
((char*)(A) >= S->base && (char*)(A) < S->base + S->size) |
/* Return segment holding given address */ |
static msegmentptr segment_holding(mstate m, char* addr) { |
msegmentptr sp = &m->seg; |
for (;;) { |
if (addr >= sp->base && addr < sp->base + sp->size) |
return sp; |
if ((sp = sp->next) == 0) |
return 0; |
} |
} |
/* Return true if segment contains a segment link */ |
static int has_segment_link(mstate m, msegmentptr ss) { |
msegmentptr sp = &m->seg; |
for (;;) { |
if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) |
return 1; |
if ((sp = sp->next) == 0) |
return 0; |
} |
} |
#ifndef MORECORE_CANNOT_TRIM |
#define should_trim(M,s) ((s) > (M)->trim_check) |
#else /* MORECORE_CANNOT_TRIM */ |
#define should_trim(M,s) (0) |
#endif /* MORECORE_CANNOT_TRIM */ |
/* |
TOP_FOOT_SIZE is padding at the end of a segment, including space |
that may be needed to place segment records and fenceposts when new |
noncontiguous segments are added. |
*/ |
#define TOP_FOOT_SIZE\ |
(align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) |
/* ------------------------------- Hooks -------------------------------- */ |
/* |
PREACTION should be defined to return 0 on success, and nonzero on |
failure. If you are not using locking, you can redefine these to do |
anything you like. |
*/ |
#if USE_LOCKS |
/* Ensure locks are initialized */ |
#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams()) |
#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) |
#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } |
#else /* USE_LOCKS */ |
#ifndef PREACTION |
#define PREACTION(M) (0) |
#endif /* PREACTION */ |
#ifndef POSTACTION |
#define POSTACTION(M) |
#endif /* POSTACTION */ |
#endif /* USE_LOCKS */ |
/* |
CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. |
USAGE_ERROR_ACTION is triggered on detected bad frees and |
reallocs. The argument p is an address that might have triggered the |
fault. It is ignored by the two predefined actions, but might be |
useful in custom actions that try to help diagnose errors. |
*/ |
#if PROCEED_ON_ERROR |
/* A count of the number of corruption errors causing resets */ |
int malloc_corruption_error_count; |
/* default corruption action */ |
static void reset_on_error(mstate m); |
#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) |
#define USAGE_ERROR_ACTION(m, p) |
#else /* PROCEED_ON_ERROR */ |
#ifndef CORRUPTION_ERROR_ACTION |
#define CORRUPTION_ERROR_ACTION(m) ABORT |
#endif /* CORRUPTION_ERROR_ACTION */ |
#ifndef USAGE_ERROR_ACTION |
#define USAGE_ERROR_ACTION(m,p) ABORT |
#endif /* USAGE_ERROR_ACTION */ |
#endif /* PROCEED_ON_ERROR */ |
/* -------------------------- Debugging setup ---------------------------- */ |
//#ifdef !DEBUG |
#define check_free_chunk(M,P) |
#define check_inuse_chunk(M,P) |
#define check_malloced_chunk(M,P,N) |
#define check_mmapped_chunk(M,P) |
#define check_malloc_state(M) |
#define check_top_chunk(M,P) |
//#else /* DEBUG */ |
//#define check_free_chunk(M,P) do_check_free_chunk(M,P) |
//#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) |
//#define check_top_chunk(M,P) do_check_top_chunk(M,P) |
//#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) |
//#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) |
//#define check_malloc_state(M) do_check_malloc_state(M) |
//static void do_check_any_chunk(mstate m, mchunkptr p); |
//static void do_check_top_chunk(mstate m, mchunkptr p); |
//static void do_check_mmapped_chunk(mstate m, mchunkptr p); |
//static void do_check_inuse_chunk(mstate m, mchunkptr p); |
//static void do_check_free_chunk(mstate m, mchunkptr p); |
//static void do_check_malloced_chunk(mstate m, void* mem, size_t s); |
//static void do_check_tree(mstate m, tchunkptr t); |
//static void do_check_treebin(mstate m, bindex_t i); |
//static void do_check_smallbin(mstate m, bindex_t i); |
//static void do_check_malloc_state(mstate m); |
//static int bin_find(mstate m, mchunkptr x); |
//static size_t traverse_and_check(mstate m); |
//#endif /* DEBUG */ |
/* ---------------------------- Indexing Bins ---------------------------- */ |
#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) |
#define small_index(s) ((s) >> SMALLBIN_SHIFT) |
#define small_index2size(i) ((i) << SMALLBIN_SHIFT) |
#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) |
/* addressing by index. See above about smallbin repositioning */ |
#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) |
#define treebin_at(M,i) (&((M)->treebins[i])) |
/* assign tree index for size S to variable I */ |
#if defined(__GNUC__) && defined(i386) |
#define compute_tree_index(S, I)\ |
{\ |
size_t X = S >> TREEBIN_SHIFT;\ |
if (X == 0)\ |
I = 0;\ |
else if (X > 0xFFFF)\ |
I = NTREEBINS-1;\ |
else {\ |
unsigned int K;\ |
__asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\ |
I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ |
}\ |
} |
#else /* GNUC */ |
#define compute_tree_index(S, I)\ |
{\ |
size_t X = S >> TREEBIN_SHIFT;\ |
if (X == 0)\ |
I = 0;\ |
else if (X > 0xFFFF)\ |
I = NTREEBINS-1;\ |
else {\ |
unsigned int Y = (unsigned int)X;\ |
unsigned int N = ((Y - 0x100) >> 16) & 8;\ |
unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ |
N += K;\ |
N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ |
K = 14 - N + ((Y <<= K) >> 15);\ |
I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ |
}\ |
} |
#endif /* GNUC */ |
/* Bit representing maximum resolved size in a treebin at i */ |
#define bit_for_tree_index(i) \ |
(i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) |
/* Shift placing maximum resolved bit in a treebin at i as sign bit */ |
#define leftshift_for_tree_index(i) \ |
((i == NTREEBINS-1)? 0 : \ |
((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) |
/* The size of the smallest chunk held in bin with index i */ |
#define minsize_for_tree_index(i) \ |
((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ |
(((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) |
/* ------------------------ Operations on bin maps ----------------------- */ |
/* bit corresponding to given index */ |
#define idx2bit(i) ((binmap_t)(1) << (i)) |
/* Mark/Clear bits with given index */ |
#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) |
#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) |
#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) |
#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) |
#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) |
#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) |
/* index corresponding to given bit */ |
#if defined(__GNUC__) && defined(i386) |
#define compute_bit2idx(X, I)\ |
{\ |
unsigned int J;\ |
__asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\ |
I = (bindex_t)J;\ |
} |
#else /* GNUC */ |
#if USE_BUILTIN_FFS |
#define compute_bit2idx(X, I) I = ffs(X)-1 |
#else /* USE_BUILTIN_FFS */ |
#define compute_bit2idx(X, I)\ |
{\ |
unsigned int Y = X - 1;\ |
unsigned int K = Y >> (16-4) & 16;\ |
unsigned int N = K; Y >>= K;\ |
N += K = Y >> (8-3) & 8; Y >>= K;\ |
N += K = Y >> (4-2) & 4; Y >>= K;\ |
N += K = Y >> (2-1) & 2; Y >>= K;\ |
N += K = Y >> (1-0) & 1; Y >>= K;\ |
I = (bindex_t)(N + Y);\ |
} |
#endif /* USE_BUILTIN_FFS */ |
#endif /* GNUC */ |
/* isolate the least set bit of a bitmap */ |
#define least_bit(x) ((x) & -(x)) |
/* mask with all bits to left of least bit of x on */ |
#define left_bits(x) ((x<<1) | -(x<<1)) |
/* mask with all bits to left of or equal to least bit of x on */ |
#define same_or_left_bits(x) ((x) | -(x)) |
/* ----------------------- Runtime Check Support ------------------------- */ |
/* |
For security, the main invariant is that malloc/free/etc never |
writes to a static address other than malloc_state, unless static |
malloc_state itself has been corrupted, which cannot occur via |
malloc (because of these checks). In essence this means that we |
believe all pointers, sizes, maps etc held in malloc_state, but |
check all of those linked or offsetted from other embedded data |
structures. These checks are interspersed with main code in a way |
that tends to minimize their run-time cost. |
When FOOTERS is defined, in addition to range checking, we also |
verify footer fields of inuse chunks, which can be used guarantee |
that the mstate controlling malloc/free is intact. This is a |
streamlined version of the approach described by William Robertson |
et al in "Run-time Detection of Heap-based Overflows" LISA'03 |
http://www.usenix.org/events/lisa03/tech/robertson.html The footer |
of an inuse chunk holds the xor of its mstate and a random seed, |
that is checked upon calls to free() and realloc(). This is |
(probablistically) unguessable from outside the program, but can be |
computed by any code successfully malloc'ing any chunk, so does not |
itself provide protection against code that has already broken |
security through some other means. Unlike Robertson et al, we |
always dynamically check addresses of all offset chunks (previous, |
next, etc). This turns out to be cheaper than relying on hashes. |
*/ |
#if !INSECURE |
/* Check if address a is at least as high as any from MORECORE or MMAP */ |
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) |
/* Check if address of next chunk n is higher than base chunk p */ |
#define ok_next(p, n) ((char*)(p) < (char*)(n)) |
/* Check if p has its cinuse bit on */ |
#define ok_cinuse(p) cinuse(p) |
/* Check if p has its pinuse bit on */ |
#define ok_pinuse(p) pinuse(p) |
#else /* !INSECURE */ |
#define ok_address(M, a) (1) |
#define ok_next(b, n) (1) |
#define ok_cinuse(p) (1) |
#define ok_pinuse(p) (1) |
#endif /* !INSECURE */ |
#if (FOOTERS && !INSECURE) |
/* Check if (alleged) mstate m has expected magic field */ |
#define ok_magic(M) ((M)->magic == mparams.magic) |
#else /* (FOOTERS && !INSECURE) */ |
#define ok_magic(M) (1) |
#endif /* (FOOTERS && !INSECURE) */ |
/* In gcc, use __builtin_expect to minimize impact of checks */ |
#if !INSECURE |
//#if defined(__GNUC__) && __GNUC__ >= 3 |
//#define RTCHECK(e) __builtin_expect(e, 1) |
//#else /* GNUC */ |
#define RTCHECK(e) (e) |
//#endif /* GNUC */ |
//#else /* !INSECURE */ |
//#define RTCHECK(e) (1) |
#endif /* !INSECURE */ |
/* macros to set up inuse chunks with or without footers */ |
#if !FOOTERS |
#define mark_inuse_foot(M,p,s) |
/* Set cinuse bit and pinuse bit of next chunk */ |
#define set_inuse(M,p,s)\ |
((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ |
((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) |
/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ |
#define set_inuse_and_pinuse(M,p,s)\ |
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ |
((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) |
/* Set size, cinuse and pinuse bit of this chunk */ |
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ |
((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) |
#else /* FOOTERS */ |
/* Set foot of inuse chunk to be xor of mstate and seed */ |
#define mark_inuse_foot(M,p,s)\ |
(((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) |
#define get_mstate_for(p)\ |
((mstate)(((mchunkptr)((char*)(p) +\ |
(chunksize(p))))->prev_foot ^ mparams.magic)) |
#define set_inuse(M,p,s)\ |
((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ |
(((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ |
mark_inuse_foot(M,p,s)) |
#define set_inuse_and_pinuse(M,p,s)\ |
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ |
(((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ |
mark_inuse_foot(M,p,s)) |
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ |
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ |
mark_inuse_foot(M, p, s)) |
#endif /* !FOOTERS */ |
/* ---------------------------- setting mparams -------------------------- */ |
/* Initialize mparams */ |
static int init_mparams(void) { |
if (mparams.page_size == 0) { |
size_t s; |
mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; |
mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; |
#if MORECORE_CONTIGUOUS |
mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; |
#else /* MORECORE_CONTIGUOUS */ |
mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; |
#endif /* MORECORE_CONTIGUOUS */ |
#if (FOOTERS && !INSECURE) |
{ |
#if USE_DEV_RANDOM |
int fd; |
unsigned char buf[sizeof(size_t)]; |
/* Try to use /dev/urandom, else fall back on using time */ |
if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && |
read(fd, buf, sizeof(buf)) == sizeof(buf)) { |
s = *((size_t *) buf); |
close(fd); |
} |
else |
#endif /* USE_DEV_RANDOM */ |
s = (size_t)(time(0) ^ (size_t)0x55555555U); |
s |= (size_t)8U; /* ensure nonzero */ |
s &= ~(size_t)7U; /* improve chances of fault for bad values */ |
} |
#else /* (FOOTERS && !INSECURE) */ |
s = (size_t)0x58585858U; |
#endif /* (FOOTERS && !INSECURE) */ |
ACQUIRE_MAGIC_INIT_LOCK(); |
if (mparams.magic == 0) { |
mparams.magic = s; |
/* Set up lock for main malloc area */ |
INITIAL_LOCK(&gm->mutex); |
gm->mflags = mparams.default_mflags; |
} |
RELEASE_MAGIC_INIT_LOCK(); |
//#ifndef WIN32 |
// mparams.page_size = 4096; |
// mparams.granularity = ((DEFAULT_GRANULARITY != 0)? |
// DEFAULT_GRANULARITY : mparams.page_size); |
//#else /* WIN32 */ |
// { |
mparams.page_size = 4096; |
mparams.granularity = 16384; |
// } |
//#endif /* WIN32 */ |
/* Sanity-check configuration: |
size_t must be unsigned and as wide as pointer type. |
ints must be at least 4 bytes. |
alignment must be at least 8. |
Alignment, min chunk size, and page size must all be powers of 2. |
*/ |
if ((sizeof(size_t) != sizeof(char*)) || |
(MAX_SIZE_T < MIN_CHUNK_SIZE) || |
(sizeof(int) < 4) || |
(MALLOC_ALIGNMENT < (size_t)8U) || |
((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || |
((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || |
((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) || |
((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0)) |
ABORT; |
} |
return 0; |
} |
/* support for mallopt */ |
static int change_mparam(int param_number, int value) { |
size_t val = (size_t)value; |
init_mparams(); |
switch(param_number) { |
case M_TRIM_THRESHOLD: |
mparams.trim_threshold = val; |
return 1; |
case M_GRANULARITY: |
if (val >= mparams.page_size && ((val & (val-1)) == 0)) { |
mparams.granularity = val; |
return 1; |
} |
else |
return 0; |
case M_MMAP_THRESHOLD: |
mparams.mmap_threshold = val; |
return 1; |
default: |
return 0; |
} |
} |
#ifdef DEBUG |
#endif /* DEBUG */ |
/* ----------------------------- statistics ------------------------------ */ |
#if !NO_MALLINFO |
#endif /* !NO_MALLINFO */ |
/* ----------------------- Operations on smallbins ----------------------- */ |
/* |
Various forms of linking and unlinking are defined as macros. Even |
the ones for trees, which are very long but have very short typical |
paths. This is ugly but reduces reliance on inlining support of |
compilers. |
*/ |
/* Link a free chunk into a smallbin */ |
#define insert_small_chunk(M, P, S) {\ |
bindex_t I = small_index(S);\ |
mchunkptr B = smallbin_at(M, I);\ |
mchunkptr F = B;\ |
assert(S >= MIN_CHUNK_SIZE);\ |
if (!smallmap_is_marked(M, I))\ |
mark_smallmap(M, I);\ |
else if (RTCHECK(ok_address(M, B->fd)))\ |
F = B->fd;\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
B->fd = P;\ |
F->bk = P;\ |
P->fd = F;\ |
P->bk = B;\ |
} |
/* Unlink a chunk from a smallbin */ |
#define unlink_small_chunk(M, P, S) {\ |
mchunkptr F = P->fd;\ |
mchunkptr B = P->bk;\ |
bindex_t I = small_index(S);\ |
assert(P != B);\ |
assert(P != F);\ |
assert(chunksize(P) == small_index2size(I));\ |
if (F == B)\ |
clear_smallmap(M, I);\ |
else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ |
(B == smallbin_at(M,I) || ok_address(M, B)))) {\ |
F->bk = B;\ |
B->fd = F;\ |
}\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
} |
/* Unlink the first chunk from a smallbin */ |
#define unlink_first_small_chunk(M, B, P, I) {\ |
mchunkptr F = P->fd;\ |
assert(P != B);\ |
assert(P != F);\ |
assert(chunksize(P) == small_index2size(I));\ |
if (B == F)\ |
clear_smallmap(M, I);\ |
else if (RTCHECK(ok_address(M, F))) {\ |
B->fd = F;\ |
F->bk = B;\ |
}\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
} |
/* Replace dv node, binning the old one */ |
/* Used only when dvsize known to be small */ |
#define replace_dv(M, P, S) {\ |
size_t DVS = M->dvsize;\ |
if (DVS != 0) {\ |
mchunkptr DV = M->dv;\ |
assert(is_small(DVS));\ |
insert_small_chunk(M, DV, DVS);\ |
}\ |
M->dvsize = S;\ |
M->dv = P;\ |
} |
/* ------------------------- Operations on trees ------------------------- */ |
/* Insert chunk into tree */ |
#define insert_large_chunk(M, X, S) {\ |
tbinptr* H;\ |
bindex_t I;\ |
compute_tree_index(S, I);\ |
H = treebin_at(M, I);\ |
X->index = I;\ |
X->child[0] = X->child[1] = 0;\ |
if (!treemap_is_marked(M, I)) {\ |
mark_treemap(M, I);\ |
*H = X;\ |
X->parent = (tchunkptr)H;\ |
X->fd = X->bk = X;\ |
}\ |
else {\ |
tchunkptr T = *H;\ |
size_t K = S << leftshift_for_tree_index(I);\ |
for (;;) {\ |
if (chunksize(T) != S) {\ |
tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ |
K <<= 1;\ |
if (*C != 0)\ |
T = *C;\ |
else if (RTCHECK(ok_address(M, C))) {\ |
*C = X;\ |
X->parent = T;\ |
X->fd = X->bk = X;\ |
break;\ |
}\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
break;\ |
}\ |
}\ |
else {\ |
tchunkptr F = T->fd;\ |
if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ |
T->fd = F->bk = X;\ |
X->fd = F;\ |
X->bk = T;\ |
X->parent = 0;\ |
break;\ |
}\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
break;\ |
}\ |
}\ |
}\ |
}\ |
} |
/* |
Unlink steps: |
1. If x is a chained node, unlink it from its same-sized fd/bk links |
and choose its bk node as its replacement. |
2. If x was the last node of its size, but not a leaf node, it must |
be replaced with a leaf node (not merely one with an open left or |
right), to make sure that lefts and rights of descendents |
correspond properly to bit masks. We use the rightmost descendent |
of x. We could use any other leaf, but this is easy to locate and |
tends to counteract removal of leftmosts elsewhere, and so keeps |
paths shorter than minimally guaranteed. This doesn't loop much |
because on average a node in a tree is near the bottom. |
3. If x is the base of a chain (i.e., has parent links) relink |
x's parent and children to x's replacement (or null if none). |
*/ |
#define unlink_large_chunk(M, X) {\ |
tchunkptr XP = X->parent;\ |
tchunkptr R;\ |
if (X->bk != X) {\ |
tchunkptr F = X->fd;\ |
R = X->bk;\ |
if (RTCHECK(ok_address(M, F))) {\ |
F->bk = R;\ |
R->fd = F;\ |
}\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
}\ |
else {\ |
tchunkptr* RP;\ |
if (((R = *(RP = &(X->child[1]))) != 0) ||\ |
((R = *(RP = &(X->child[0]))) != 0)) {\ |
tchunkptr* CP;\ |
while ((*(CP = &(R->child[1])) != 0) ||\ |
(*(CP = &(R->child[0])) != 0)) {\ |
R = *(RP = CP);\ |
}\ |
if (RTCHECK(ok_address(M, RP)))\ |
*RP = 0;\ |
else {\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
}\ |
}\ |
if (XP != 0) {\ |
tbinptr* H = treebin_at(M, X->index);\ |
if (X == *H) {\ |
if ((*H = R) == 0) \ |
clear_treemap(M, X->index);\ |
}\ |
else if (RTCHECK(ok_address(M, XP))) {\ |
if (XP->child[0] == X) \ |
XP->child[0] = R;\ |
else \ |
XP->child[1] = R;\ |
}\ |
else\ |
CORRUPTION_ERROR_ACTION(M);\ |
if (R != 0) {\ |
if (RTCHECK(ok_address(M, R))) {\ |
tchunkptr C0, C1;\ |
R->parent = XP;\ |
if ((C0 = X->child[0]) != 0) {\ |
if (RTCHECK(ok_address(M, C0))) {\ |
R->child[0] = C0;\ |
C0->parent = R;\ |
}\ |
else\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
if ((C1 = X->child[1]) != 0) {\ |
if (RTCHECK(ok_address(M, C1))) {\ |
R->child[1] = C1;\ |
C1->parent = R;\ |
}\ |
else\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
}\ |
else\ |
CORRUPTION_ERROR_ACTION(M);\ |
}\ |
}\ |
} |
/* Relays to large vs small bin operations */ |
#define insert_chunk(M, P, S)\ |
if (is_small(S)) insert_small_chunk(M, P, S)\ |
else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } |
#define unlink_chunk(M, P, S)\ |
if (is_small(S)) unlink_small_chunk(M, P, S)\ |
else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } |
/* Relays to internal calls to malloc/free from realloc, memalign etc */ |
#if ONLY_MSPACES |
#define internal_malloc(m, b) mspace_malloc(m, b) |
#define internal_free(m, mem) mspace_free(m,mem); |
#else /* ONLY_MSPACES */ |
#if MSPACES |
#define internal_malloc(m, b)\ |
(m == gm)? dlmalloc(b) : mspace_malloc(m, b) |
#define internal_free(m, mem)\ |
if (m == gm) dlfree(mem); else mspace_free(m,mem); |
#else /* MSPACES */ |
#define internal_malloc(m, b) dlmalloc(b) |
#define internal_free(m, mem) dlfree(mem) |
#endif /* MSPACES */ |
#endif /* ONLY_MSPACES */ |
/* ----------------------- Direct-mmapping chunks ----------------------- */ |
/* |
Directly mmapped chunks are set up with an offset to the start of |
the mmapped region stored in the prev_foot field of the chunk. This |
allows reconstruction of the required argument to MUNMAP when freed, |
and also allows adjustment of the returned chunk to meet alignment |
requirements (especially in memalign). There is also enough space |
allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain |
the PINUSE bit so frees can be checked. |
*/ |
/* Malloc using mmap */ |
static void* mmap_alloc(mstate m, size_t nb) { |
size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); |
if (mmsize > nb) { /* Check for wrap around 0 */ |
char* mm = (char*)(gui_ksys_mem_alloc(mmsize)); |
if (mm != CMFAIL) { |
size_t offset = align_offset(chunk2mem(mm)); |
size_t psize = mmsize - offset - MMAP_FOOT_PAD; |
mchunkptr p = (mchunkptr)(mm + offset); |
p->prev_foot = offset | IS_MMAPPED_BIT; |
(p)->head = (psize|CINUSE_BIT); |
mark_inuse_foot(m, p, psize); |
chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; |
chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; |
if (mm < m->least_addr) |
m->least_addr = mm; |
if ((m->footprint += mmsize) > m->max_footprint) |
m->max_footprint = m->footprint; |
assert(is_aligned(chunk2mem(p))); |
check_mmapped_chunk(m, p); |
return chunk2mem(p); |
} |
} |
return 0; |
} |
/* Realloc using mmap */ |
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { |
size_t oldsize = chunksize(oldp); |
if (is_small(nb)) /* Can't shrink mmap regions below small size */ |
return 0; |
/* Keep old chunk if big enough but not too big */ |
if (oldsize >= nb + SIZE_T_SIZE && |
(oldsize - nb) <= (mparams.granularity << 1)) |
return oldp; |
else { |
size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT; |
size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; |
size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES + |
CHUNK_ALIGN_MASK); |
char* cp = (char*)CALL_MREMAP((char*)oldp - offset, |
oldmmsize, newmmsize, 1); |
if (cp != CMFAIL) { |
mchunkptr newp = (mchunkptr)(cp + offset); |
size_t psize = newmmsize - offset - MMAP_FOOT_PAD; |
newp->head = (psize|CINUSE_BIT); |
mark_inuse_foot(m, newp, psize); |
chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; |
chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; |
if (cp < m->least_addr) |
m->least_addr = cp; |
if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) |
m->max_footprint = m->footprint; |
check_mmapped_chunk(m, newp); |
return newp; |
} |
} |
return 0; |
} |
/* -------------------------- mspace management -------------------------- */ |
/* Initialize top chunk and its size */ |
static void init_top(mstate m, mchunkptr p, size_t psize) { |
/* Ensure alignment */ |
size_t offset = align_offset(chunk2mem(p)); |
p = (mchunkptr)((char*)p + offset); |
psize -= offset; |
m->top = p; |
m->topsize = psize; |
p->head = psize | PINUSE_BIT; |
/* set size of fake trailing chunk holding overhead space only once */ |
chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; |
m->trim_check = mparams.trim_threshold; /* reset on each update */ |
} |
/* Initialize bins for a new mstate that is otherwise zeroed out */ |
static void init_bins(mstate m) { |
/* Establish circular links for smallbins */ |
bindex_t i; |
for (i = 0; i < NSMALLBINS; ++i) { |
sbinptr bin = smallbin_at(m,i); |
bin->fd = bin->bk = bin; |
} |
} |
#if PROCEED_ON_ERROR |
/* default corruption action */ |
static void reset_on_error(mstate m) { |
int i; |
++malloc_corruption_error_count; |
/* Reinitialize fields to forget about all memory */ |
m->smallbins = m->treebins = 0; |
m->dvsize = m->topsize = 0; |
m->seg.base = 0; |
m->seg.size = 0; |
m->seg.next = 0; |
m->top = m->dv = 0; |
for (i = 0; i < NTREEBINS; ++i) |
*treebin_at(m, i) = 0; |
init_bins(m); |
} |
#endif /* PROCEED_ON_ERROR */ |
/* Allocate chunk and prepend remainder with chunk in successor base. */ |
static void* prepend_alloc(mstate m, char* newbase, char* oldbase, |
size_t nb) { |
mchunkptr p = align_as_chunk(newbase); |
mchunkptr oldfirst = align_as_chunk(oldbase); |
size_t psize = (char*)oldfirst - (char*)p; |
mchunkptr q = chunk_plus_offset(p, nb); |
size_t qsize = psize - nb; |
set_size_and_pinuse_of_inuse_chunk(m, p, nb); |
assert((char*)oldfirst > (char*)q); |
assert(pinuse(oldfirst)); |
assert(qsize >= MIN_CHUNK_SIZE); |
/* consolidate remainder with first chunk of old base */ |
if (oldfirst == m->top) { |
size_t tsize = m->topsize += qsize; |
m->top = q; |
q->head = tsize | PINUSE_BIT; |
check_top_chunk(m, q); |
} |
else if (oldfirst == m->dv) { |
size_t dsize = m->dvsize += qsize; |
m->dv = q; |
set_size_and_pinuse_of_free_chunk(q, dsize); |
} |
else { |
if (!cinuse(oldfirst)) { |
size_t nsize = chunksize(oldfirst); |
unlink_chunk(m, oldfirst, nsize); |
oldfirst = chunk_plus_offset(oldfirst, nsize); |
qsize += nsize; |
} |
set_free_with_pinuse(q, qsize, oldfirst); |
insert_chunk(m, q, qsize); |
check_free_chunk(m, q); |
} |
check_malloced_chunk(m, chunk2mem(p), nb); |
return chunk2mem(p); |
} |
/* Add a segment to hold a new noncontiguous region */ |
static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { |
/* Determine locations and sizes of segment, fenceposts, old top */ |
char* old_top = (char*)m->top; |
msegmentptr oldsp = segment_holding(m, old_top); |
char* old_end = oldsp->base + oldsp->size; |
size_t ssize = pad_request(sizeof(struct malloc_segment)); |
char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); |
size_t offset = align_offset(chunk2mem(rawsp)); |
char* asp = rawsp + offset; |
char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; |
mchunkptr sp = (mchunkptr)csp; |
msegmentptr ss = (msegmentptr)(chunk2mem(sp)); |
mchunkptr tnext = chunk_plus_offset(sp, ssize); |
mchunkptr p = tnext; |
int nfences = 0; |
/* reset top to new space */ |
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); |
/* Set up segment record */ |
assert(is_aligned(ss)); |
set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); |
*ss = m->seg; /* Push current record */ |
m->seg.base = tbase; |
m->seg.size = tsize; |
m->seg.sflags = mmapped; |
m->seg.next = ss; |
/* Insert trailing fenceposts */ |
for (;;) { |
mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); |
p->head = FENCEPOST_HEAD; |
++nfences; |
if ((char*)(&(nextp->head)) < old_end) |
p = nextp; |
else |
break; |
} |
assert(nfences >= 2); |
/* Insert the rest of old top into a bin as an ordinary free chunk */ |
if (csp != old_top) { |
mchunkptr q = (mchunkptr)old_top; |
size_t psize = csp - old_top; |
mchunkptr tn = chunk_plus_offset(q, psize); |
set_free_with_pinuse(q, psize, tn); |
insert_chunk(m, q, psize); |
} |
check_top_chunk(m, m->top); |
} |
/* -------------------------- System allocation -------------------------- */ |
/* Get memory from system using MORECORE or MMAP */ |
static void* sys_alloc(mstate m, size_t nb) { |
char* tbase = CMFAIL; |
size_t tsize = 0; |
flag_t mmap_flag = 0; |
init_mparams(); |
/* Directly map large chunks */ |
if (use_mmap(m) && nb >= mparams.mmap_threshold) { |
void* mem = mmap_alloc(m, nb); |
if (mem != 0) |
return mem; |
} |
/* |
Try getting memory in any of three ways (in most-preferred to |
least-preferred order): |
1. A call to MORECORE that can normally contiguously extend memory. |
(disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or |
or main space is mmapped or a previous contiguous call failed) |
2. A call to MMAP new space (disabled if not HAVE_MMAP). |
Note that under the default settings, if MORECORE is unable to |
fulfill a request, and HAVE_MMAP is true, then mmap is |
used as a noncontiguous system allocator. This is a useful backup |
strategy for systems with holes in address spaces -- in this case |
sbrk cannot contiguously expand the heap, but mmap may be able to |
find space. |
3. A call to MORECORE that cannot usually contiguously extend memory. |
(disabled if not HAVE_MORECORE) |
*/ |
if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { |
char* br = CMFAIL; |
msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); |
size_t asize = 0; |
ACQUIRE_MORECORE_LOCK(); |
if (ss == 0) { /* First time through or recovery */ |
char* base = (char*)CALL_MORECORE(0); |
if (base != CMFAIL) { |
asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); |
/* Adjust to end on a page boundary */ |
if (!is_page_aligned(base)) |
asize += (page_align((size_t)base) - (size_t)base); |
/* Can't call MORECORE if size is negative when treated as signed */ |
if (asize < HALF_MAX_SIZE_T && |
(br = (char*)(CALL_MORECORE(asize))) == base) { |
tbase = base; |
tsize = asize; |
} |
} |
} |
else { |
/* Subtract out existing available top space from MORECORE request. */ |
asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE); |
/* Use mem here only if it did continuously extend old space */ |
if (asize < HALF_MAX_SIZE_T && |
(br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { |
tbase = br; |
tsize = asize; |
} |
} |
if (tbase == CMFAIL) { /* Cope with partial failure */ |
if (br != CMFAIL) { /* Try to use/extend the space we did get */ |
if (asize < HALF_MAX_SIZE_T && |
asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) { |
size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize); |
if (esize < HALF_MAX_SIZE_T) { |
char* end = (char*)CALL_MORECORE(esize); |
if (end != CMFAIL) |
asize += esize; |
else { /* Can't use; try to release */ |
CALL_MORECORE(-asize); |
br = CMFAIL; |
} |
} |
} |
} |
if (br != CMFAIL) { /* Use the space we did get */ |
tbase = br; |
tsize = asize; |
} |
else |
disable_contiguous(m); /* Don't try contiguous path in the future */ |
} |
RELEASE_MORECORE_LOCK(); |
} |
if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ |
size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; |
size_t rsize = granularity_align(req); |
if (rsize > nb) { /* Fail if wraps around zero */ |
char* mp = (char*)(gui_ksys_mem_alloc(rsize)); |
if (mp != CMFAIL) { |
tbase = mp; |
tsize = rsize; |
mmap_flag = IS_MMAPPED_BIT; |
} |
} |
} |
if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ |
size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); |
if (asize < HALF_MAX_SIZE_T) { |
char* br = CMFAIL; |
char* end = CMFAIL; |
ACQUIRE_MORECORE_LOCK(); |
br = (char*)(CALL_MORECORE(asize)); |
end = (char*)(CALL_MORECORE(0)); |
RELEASE_MORECORE_LOCK(); |
if (br != CMFAIL && end != CMFAIL && br < end) { |
size_t ssize = end - br; |
if (ssize > nb + TOP_FOOT_SIZE) { |
tbase = br; |
tsize = ssize; |
} |
} |
} |
} |
if (tbase != CMFAIL) { |
if ((m->footprint += tsize) > m->max_footprint) |
m->max_footprint = m->footprint; |
if (!is_initialized(m)) { /* first-time initialization */ |
m->seg.base = m->least_addr = tbase; |
m->seg.size = tsize; |
m->seg.sflags = mmap_flag; |
m->magic = mparams.magic; |
init_bins(m); |
if (is_global(m)) |
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); |
else { |
/* Offset top by embedded malloc_state */ |
mchunkptr mn = next_chunk(mem2chunk(m)); |
init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); |
} |
} |
else { |
/* Try to merge with an existing segment */ |
msegmentptr sp = &m->seg; |
while (sp != 0 && tbase != sp->base + sp->size) |
sp = sp->next; |
if (sp != 0 && |
!is_extern_segment(sp) && |
(sp->sflags & IS_MMAPPED_BIT) == mmap_flag && |
segment_holds(sp, m->top)) { /* append */ |
sp->size += tsize; |
init_top(m, m->top, m->topsize + tsize); |
} |
else { |
if (tbase < m->least_addr) |
m->least_addr = tbase; |
sp = &m->seg; |
while (sp != 0 && sp->base != tbase + tsize) |
sp = sp->next; |
if (sp != 0 && |
!is_extern_segment(sp) && |
(sp->sflags & IS_MMAPPED_BIT) == mmap_flag) { |
char* oldbase = sp->base; |
sp->base = tbase; |
sp->size += tsize; |
return prepend_alloc(m, tbase, oldbase, nb); |
} |
else |
add_segment(m, tbase, tsize, mmap_flag); |
} |
} |
if (nb < m->topsize) { /* Allocate from new or extended top space */ |
size_t rsize = m->topsize -= nb; |
mchunkptr p = m->top; |
mchunkptr r = m->top = chunk_plus_offset(p, nb); |
r->head = rsize | PINUSE_BIT; |
set_size_and_pinuse_of_inuse_chunk(m, p, nb); |
check_top_chunk(m, m->top); |
check_malloced_chunk(m, chunk2mem(p), nb); |
return chunk2mem(p); |
} |
} |
MALLOC_FAILURE_ACTION; |
return 0; |
} |
/* ----------------------- system deallocation -------------------------- */ |
/* Unmap and unlink any mmapped segments that don't contain used chunks */ |
static size_t release_unused_segments(mstate m) { |
size_t released = 0; |
msegmentptr pred = &m->seg; |
msegmentptr sp = pred->next; |
while (sp != 0) { |
char* base = sp->base; |
size_t size = sp->size; |
msegmentptr next = sp->next; |
if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { |
mchunkptr p = align_as_chunk(base); |
size_t psize = chunksize(p); |
/* Can unmap if first chunk holds entire segment and not pinned */ |
if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { |
tchunkptr tp = (tchunkptr)p; |
assert(segment_holds(sp, (char*)sp)); |
if (p == m->dv) { |
m->dv = 0; |
m->dvsize = 0; |
} |
else { |
unlink_large_chunk(m, tp); |
} |
if (gui_ksys_mem_free(base, size) == 0) { |
released += size; |
m->footprint -= size; |
/* unlink obsoleted record */ |
sp = pred; |
sp->next = next; |
} |
else { /* back out if cannot unmap */ |
insert_large_chunk(m, tp, psize); |
} |
} |
} |
pred = sp; |
sp = next; |
} |
return released; |
} |
static int sys_trim(mstate m, size_t pad) { |
size_t released = 0; |
if (pad < MAX_REQUEST && is_initialized(m)) { |
pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ |
if (m->topsize > pad) { |
/* Shrink top space in granularity-size units, keeping at least one */ |
size_t unit = mparams.granularity; |
size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - |
SIZE_T_ONE) * unit; |
msegmentptr sp = segment_holding(m, (char*)m->top); |
if (!is_extern_segment(sp)) { |
if (is_mmapped_segment(sp)) { |
if (HAVE_MMAP && |
sp->size >= extra && |
!has_segment_link(m, sp)) { /* can't shrink if pinned */ |
size_t newsize = sp->size - extra; |
/* Prefer mremap, fall back to munmap */ |
if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || |
(gui_ksys_mem_free(sp->base + newsize, extra) == 0)) { |
released = extra; |
} |
} |
} |
else if (HAVE_MORECORE) { |
if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ |
extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; |
ACQUIRE_MORECORE_LOCK(); |
{ |
/* Make sure end of memory is where we last set it. */ |
char* old_br = (char*)(CALL_MORECORE(0)); |
if (old_br == sp->base + sp->size) { |
char* rel_br = (char*)(CALL_MORECORE(-extra)); |
char* new_br = (char*)(CALL_MORECORE(0)); |
if (rel_br != CMFAIL && new_br < old_br) |
released = old_br - new_br; |
} |
} |
RELEASE_MORECORE_LOCK(); |
} |
} |
if (released != 0) { |
sp->size -= released; |
m->footprint -= released; |
init_top(m, m->top, m->topsize - released); |
check_top_chunk(m, m->top); |
} |
} |
/* Unmap any unused mmapped segments */ |
if (HAVE_MMAP) |
released += release_unused_segments(m); |
/* On failure, disable autotrim to avoid repeated failed future calls */ |
if (released == 0) |
m->trim_check = MAX_SIZE_T; |
} |
return (released != 0)? 1 : 0; |
} |
/* ---------------------------- malloc support --------------------------- */ |
/* allocate a large request from the best fitting chunk in a treebin */ |
static void* tmalloc_large(mstate m, size_t nb) { |
tchunkptr v = 0; |
size_t rsize = -nb; /* Unsigned negation */ |
tchunkptr t; |
bindex_t idx; |
compute_tree_index(nb, idx); |
if ((t = *treebin_at(m, idx)) != 0) { |
/* Traverse tree for this bin looking for node with size == nb */ |
size_t sizebits = nb << leftshift_for_tree_index(idx); |
tchunkptr rst = 0; /* The deepest untaken right subtree */ |
for (;;) { |
tchunkptr rt; |
size_t trem = chunksize(t) - nb; |
if (trem < rsize) { |
v = t; |
if ((rsize = trem) == 0) |
break; |
} |
rt = t->child[1]; |
t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; |
if (rt != 0 && rt != t) |
rst = rt; |
if (t == 0) { |
t = rst; /* set t to least subtree holding sizes > nb */ |
break; |
} |
sizebits <<= 1; |
} |
} |
if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ |
binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; |
if (leftbits != 0) { |
bindex_t i; |
binmap_t leastbit = least_bit(leftbits); |
compute_bit2idx(leastbit, i); |
t = *treebin_at(m, i); |
} |
} |
while (t != 0) { /* find smallest of tree or subtree */ |
size_t trem = chunksize(t) - nb; |
if (trem < rsize) { |
rsize = trem; |
v = t; |
} |
t = leftmost_child(t); |
} |
/* If dv is a better fit, return 0 so malloc will use it */ |
if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { |
if (RTCHECK(ok_address(m, v))) { /* split */ |
mchunkptr r = chunk_plus_offset(v, nb); |
assert(chunksize(v) == rsize + nb); |
if (RTCHECK(ok_next(v, r))) { |
unlink_large_chunk(m, v); |
if (rsize < MIN_CHUNK_SIZE) |
set_inuse_and_pinuse(m, v, (rsize + nb)); |
else { |
set_size_and_pinuse_of_inuse_chunk(m, v, nb); |
set_size_and_pinuse_of_free_chunk(r, rsize); |
insert_chunk(m, r, rsize); |
} |
return chunk2mem(v); |
} |
} |
CORRUPTION_ERROR_ACTION(m); |
} |
return 0; |
} |
/* allocate a small request from the best fitting chunk in a treebin */ |
static void* tmalloc_small(mstate m, size_t nb) { |
tchunkptr t, v; |
size_t rsize; |
bindex_t i; |
binmap_t leastbit = least_bit(m->treemap); |
compute_bit2idx(leastbit, i); |
v = t = *treebin_at(m, i); |
rsize = chunksize(t) - nb; |
while ((t = leftmost_child(t)) != 0) { |
size_t trem = chunksize(t) - nb; |
if (trem < rsize) { |
rsize = trem; |
v = t; |
} |
} |
if (RTCHECK(ok_address(m, v))) { |
mchunkptr r = chunk_plus_offset(v, nb); |
assert(chunksize(v) == rsize + nb); |
if (RTCHECK(ok_next(v, r))) { |
unlink_large_chunk(m, v); |
if (rsize < MIN_CHUNK_SIZE) |
set_inuse_and_pinuse(m, v, (rsize + nb)); |
else { |
set_size_and_pinuse_of_inuse_chunk(m, v, nb); |
set_size_and_pinuse_of_free_chunk(r, rsize); |
replace_dv(m, r, rsize); |
} |
return chunk2mem(v); |
} |
} |
CORRUPTION_ERROR_ACTION(m); |
return 0; |
} |
/* --------------------------- realloc support --------------------------- */ |
static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { |
if (bytes >= MAX_REQUEST) { |
MALLOC_FAILURE_ACTION; |
return 0; |
} |
if (!PREACTION(m)) { |
mchunkptr oldp = mem2chunk(oldmem); |
size_t oldsize = chunksize(oldp); |
mchunkptr next = chunk_plus_offset(oldp, oldsize); |
mchunkptr newp = 0; |
void* extra = 0; |
/* Try to either shrink or extend into top. Else malloc-copy-free */ |
if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && |
ok_next(oldp, next) && ok_pinuse(next))) { |
size_t nb = request2size(bytes); |
if (is_mmapped(oldp)) |
newp = mmap_resize(m, oldp, nb); |
else if (oldsize >= nb) { /* already big enough */ |
size_t rsize = oldsize - nb; |
newp = oldp; |
if (rsize >= MIN_CHUNK_SIZE) { |
mchunkptr remainder = chunk_plus_offset(newp, nb); |
set_inuse(m, newp, nb); |
set_inuse(m, remainder, rsize); |
extra = chunk2mem(remainder); |
} |
} |
else if (next == m->top && oldsize + m->topsize > nb) { |
/* Expand into top */ |
size_t newsize = oldsize + m->topsize; |
size_t newtopsize = newsize - nb; |
mchunkptr newtop = chunk_plus_offset(oldp, nb); |
set_inuse(m, oldp, nb); |
newtop->head = newtopsize |PINUSE_BIT; |
m->top = newtop; |
m->topsize = newtopsize; |
newp = oldp; |
} |
} |
else { |
USAGE_ERROR_ACTION(m, oldmem); |
POSTACTION(m); |
return 0; |
} |
POSTACTION(m); |
if (newp != 0) { |
if (extra != 0) { |
internal_free(m, extra); |
} |
check_inuse_chunk(m, newp); |
return chunk2mem(newp); |
} |
else { |
void* newmem = internal_malloc(m, bytes); |
if (newmem != 0) { |
size_t oc = oldsize - overhead_for(oldp); |
memcpy(newmem, oldmem, (oc < bytes)? oc : bytes); |
internal_free(m, oldmem); |
} |
return newmem; |
} |
} |
return 0; |
} |
/* --------------------------- memalign support -------------------------- */ |
static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { |
if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ |
return internal_malloc(m, bytes); |
if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ |
alignment = MIN_CHUNK_SIZE; |
if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ |
size_t a = MALLOC_ALIGNMENT << 1; |
while (a < alignment) a <<= 1; |
alignment = a; |
} |
if (bytes >= MAX_REQUEST - alignment) { |
if (m != 0) { /* Test isn't needed but avoids compiler warning */ |
MALLOC_FAILURE_ACTION; |
} |
} |
else { |
size_t nb = request2size(bytes); |
size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; |
char* mem = (char*)internal_malloc(m, req); |
if (mem != 0) { |
void* leader = 0; |
void* trailer = 0; |
mchunkptr p = mem2chunk(mem); |
if (PREACTION(m)) return 0; |
if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ |
/* |
Find an aligned spot inside chunk. Since we need to give |
back leading space in a chunk of at least MIN_CHUNK_SIZE, if |
the first calculation places us at a spot with less than |
MIN_CHUNK_SIZE leader, we can move to the next aligned spot. |
We've allocated enough total room so that this is always |
possible. |
*/ |
char* br = (char*)mem2chunk((size_t)(((size_t)(mem + |
alignment - |
SIZE_T_ONE)) & |
-alignment)); |
char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? |
br : br+alignment; |
mchunkptr newp = (mchunkptr)pos; |
size_t leadsize = pos - (char*)(p); |
size_t newsize = chunksize(p) - leadsize; |
if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ |
newp->prev_foot = p->prev_foot + leadsize; |
newp->head = (newsize|CINUSE_BIT); |
} |
else { /* Otherwise, give back leader, use the rest */ |
set_inuse(m, newp, newsize); |
set_inuse(m, p, leadsize); |
leader = chunk2mem(p); |
} |
p = newp; |
} |
/* Give back spare room at the end */ |
if (!is_mmapped(p)) { |
size_t size = chunksize(p); |
if (size > nb + MIN_CHUNK_SIZE) { |
size_t remainder_size = size - nb; |
mchunkptr remainder = chunk_plus_offset(p, nb); |
set_inuse(m, p, nb); |
set_inuse(m, remainder, remainder_size); |
trailer = chunk2mem(remainder); |
} |
} |
assert (chunksize(p) >= nb); |
assert((((size_t)(chunk2mem(p))) % alignment) == 0); |
check_inuse_chunk(m, p); |
POSTACTION(m); |
if (leader != 0) { |
internal_free(m, leader); |
} |
if (trailer != 0) { |
internal_free(m, trailer); |
} |
return chunk2mem(p); |
} |
} |
return 0; |
} |
/* ------------------------ comalloc/coalloc support --------------------- */ |
static void** ialloc(mstate m, |
size_t n_elements, |
size_t* sizes, |
int opts, |
void* chunks[]) { |
/* |
This provides common support for independent_X routines, handling |
all of the combinations that can result. |
The opts arg has: |
bit 0 set if all elements are same size (using sizes[0]) |
bit 1 set if elements should be zeroed |
*/ |
size_t element_size; /* chunksize of each element, if all same */ |
size_t contents_size; /* total size of elements */ |
size_t array_size; /* request size of pointer array */ |
void* mem; /* malloced aggregate space */ |
mchunkptr p; /* corresponding chunk */ |
size_t remainder_size; /* remaining bytes while splitting */ |
void** marray; /* either "chunks" or malloced ptr array */ |
mchunkptr array_chunk; /* chunk for malloced ptr array */ |
flag_t was_enabled; /* to disable mmap */ |
size_t size; |
size_t i; |
/* compute array length, if needed */ |
if (chunks != 0) { |
if (n_elements == 0) |
return chunks; /* nothing to do */ |
marray = chunks; |
array_size = 0; |
} |
else { |
/* if empty req, must still return chunk representing empty array */ |
if (n_elements == 0) |
return (void**)internal_malloc(m, 0); |
marray = 0; |
array_size = request2size(n_elements * (sizeof(void*))); |
} |
/* compute total element size */ |
if (opts & 0x1) { /* all-same-size */ |
element_size = request2size(*sizes); |
contents_size = n_elements * element_size; |
} |
else { /* add up all the sizes */ |
element_size = 0; |
contents_size = 0; |
for (i = 0; i != n_elements; ++i) |
contents_size += request2size(sizes[i]); |
} |
size = contents_size + array_size; |
/* |
Allocate the aggregate chunk. First disable direct-mmapping so |
malloc won't use it, since we would not be able to later |
free/realloc space internal to a segregated mmap region. |
*/ |
was_enabled = use_mmap(m); |
disable_mmap(m); |
mem = internal_malloc(m, size - CHUNK_OVERHEAD); |
if (was_enabled) |
enable_mmap(m); |
if (mem == 0) |
return 0; |
if (PREACTION(m)) return 0; |
p = mem2chunk(mem); |
remainder_size = chunksize(p); |
assert(!is_mmapped(p)); |
if (opts & 0x2) { /* optionally clear the elements */ |
memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); |
} |
/* If not provided, allocate the pointer array as final part of chunk */ |
if (marray == 0) { |
size_t array_chunk_size; |
array_chunk = chunk_plus_offset(p, contents_size); |
array_chunk_size = remainder_size - contents_size; |
marray = (void**) (chunk2mem(array_chunk)); |
set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); |
remainder_size = contents_size; |
} |
/* split out elements */ |
for (i = 0; ; ++i) { |
marray[i] = chunk2mem(p); |
if (i != n_elements-1) { |
if (element_size != 0) |
size = element_size; |
else |
size = request2size(sizes[i]); |
remainder_size -= size; |
set_size_and_pinuse_of_inuse_chunk(m, p, size); |
p = chunk_plus_offset(p, size); |
} |
else { /* the final element absorbs any overallocation slop */ |
set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); |
break; |
} |
} |
#ifdef DEBUG |
// if (marray != chunks) { |
/* final element must have exactly exhausted chunk */ |
// if (element_size != 0) { |
// assert(remainder_size == element_size); |
// } |
// else { |
// assert(remainder_size == request2size(sizes[i])); |
// } |
// check_inuse_chunk(m, mem2chunk(marray)); |
// } |
// for (i = 0; i != n_elements; ++i) |
// check_inuse_chunk(m, mem2chunk(marray[i])); |
#endif /* DEBUG */ |
POSTACTION(m); |
return marray; |
} |
/* -------------------------- public routines ---------------------------- */ |
#if !ONLY_MSPACES |
static void* dlmalloc(size_t bytes) { |
/* |
Basic algorithm: |
If a small request (< 256 bytes minus per-chunk overhead): |
1. If one exists, use a remainderless chunk in associated smallbin. |
(Remainderless means that there are too few excess bytes to |
represent as a chunk.) |
2. If it is big enough, use the dv chunk, which is normally the |
chunk adjacent to the one used for the most recent small request. |
3. If one exists, split the smallest available chunk in a bin, |
saving remainder in dv. |
4. If it is big enough, use the top chunk. |
5. If available, get memory from system and use it |
Otherwise, for a large request: |
1. Find the smallest available binned chunk that fits, and use it |
if it is better fitting than dv chunk, splitting if necessary. |
2. If better fitting than any binned chunk, use the dv chunk. |
3. If it is big enough, use the top chunk. |
4. If request size >= mmap threshold, try to directly mmap this chunk. |
5. If available, get memory from system and use it |
The ugly goto's here ensure that postaction occurs along all paths. |
*/ |
if (!PREACTION(gm)) { |
void* mem; |
size_t nb; |
if (bytes <= MAX_SMALL_REQUEST) { |
bindex_t idx; |
binmap_t smallbits; |
nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); |
idx = small_index(nb); |
smallbits = gm->smallmap >> idx; |
if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ |
mchunkptr b, p; |
idx += ~smallbits & 1; /* Uses next bin if idx empty */ |
b = smallbin_at(gm, idx); |
p = b->fd; |
assert(chunksize(p) == small_index2size(idx)); |
unlink_first_small_chunk(gm, b, p, idx); |
set_inuse_and_pinuse(gm, p, small_index2size(idx)); |
mem = chunk2mem(p); |
check_malloced_chunk(gm, mem, nb); |
goto postaction; |
} |
else if (nb > gm->dvsize) { |
if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ |
mchunkptr b, p, r; |
size_t rsize; |
bindex_t i; |
binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); |
binmap_t leastbit = least_bit(leftbits); |
compute_bit2idx(leastbit, i); |
b = smallbin_at(gm, i); |
p = b->fd; |
assert(chunksize(p) == small_index2size(i)); |
unlink_first_small_chunk(gm, b, p, i); |
rsize = small_index2size(i) - nb; |
/* Fit here cannot be remainderless if 4byte sizes */ |
if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) |
set_inuse_and_pinuse(gm, p, small_index2size(i)); |
else { |
set_size_and_pinuse_of_inuse_chunk(gm, p, nb); |
r = chunk_plus_offset(p, nb); |
set_size_and_pinuse_of_free_chunk(r, rsize); |
replace_dv(gm, r, rsize); |
} |
mem = chunk2mem(p); |
check_malloced_chunk(gm, mem, nb); |
goto postaction; |
} |
else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { |
check_malloced_chunk(gm, mem, nb); |
goto postaction; |
} |
} |
} |
else if (bytes >= MAX_REQUEST) |
nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ |
else { |
nb = pad_request(bytes); |
if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { |
check_malloced_chunk(gm, mem, nb); |
goto postaction; |
} |
} |
if (nb <= gm->dvsize) { |
size_t rsize = gm->dvsize - nb; |
mchunkptr p = gm->dv; |
if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ |
mchunkptr r = gm->dv = chunk_plus_offset(p, nb); |
gm->dvsize = rsize; |
set_size_and_pinuse_of_free_chunk(r, rsize); |
set_size_and_pinuse_of_inuse_chunk(gm, p, nb); |
} |
else { /* exhaust dv */ |
size_t dvs = gm->dvsize; |
gm->dvsize = 0; |
gm->dv = 0; |
set_inuse_and_pinuse(gm, p, dvs); |
} |
mem = chunk2mem(p); |
check_malloced_chunk(gm, mem, nb); |
goto postaction; |
} |
else if (nb < gm->topsize) { /* Split top */ |
size_t rsize = gm->topsize -= nb; |
mchunkptr p = gm->top; |
mchunkptr r = gm->top = chunk_plus_offset(p, nb); |
r->head = rsize | PINUSE_BIT; |
set_size_and_pinuse_of_inuse_chunk(gm, p, nb); |
mem = chunk2mem(p); |
check_top_chunk(gm, gm->top); |
check_malloced_chunk(gm, mem, nb); |
goto postaction; |
} |
mem = sys_alloc(gm, nb); |
postaction: |
POSTACTION(gm); |
return mem; |
} |
return 0; |
} |
static void dlfree(void* mem) { |
/* |
Consolidate freed chunks with preceeding or succeeding bordering |
free chunks, if they exist, and then place in a bin. Intermixed |
with special cases for top, dv, mmapped chunks, and usage errors. |
*/ |
if (mem != 0) { |
mchunkptr p = mem2chunk(mem); |
#if FOOTERS |
mstate fm = get_mstate_for(p); |
if (!ok_magic(fm)) { |
USAGE_ERROR_ACTION(fm, p); |
return; |
} |
#else /* FOOTERS */ |
#define fm gm |
#endif /* FOOTERS */ |
if (!PREACTION(fm)) { |
check_inuse_chunk(fm, p); |
if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { |
size_t psize = chunksize(p); |
mchunkptr next = chunk_plus_offset(p, psize); |
if (!pinuse(p)) { |
size_t prevsize = p->prev_foot; |
if ((prevsize & IS_MMAPPED_BIT) != 0) { |
prevsize &= ~IS_MMAPPED_BIT; |
psize += prevsize + MMAP_FOOT_PAD; |
if (gui_ksys_mem_free((char*)p - prevsize, psize) == 0) |
fm->footprint -= psize; |
goto postaction; |
} |
else { |
mchunkptr prev = chunk_minus_offset(p, prevsize); |
psize += prevsize; |
p = prev; |
if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ |
if (p != fm->dv) { |
unlink_chunk(fm, p, prevsize); |
} |
else if ((next->head & INUSE_BITS) == INUSE_BITS) { |
fm->dvsize = psize; |
set_free_with_pinuse(p, psize, next); |
goto postaction; |
} |
} |
else |
goto erroraction; |
} |
} |
if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { |
if (!cinuse(next)) { /* consolidate forward */ |
if (next == fm->top) { |
size_t tsize = fm->topsize += psize; |
fm->top = p; |
p->head = tsize | PINUSE_BIT; |
if (p == fm->dv) { |
fm->dv = 0; |
fm->dvsize = 0; |
} |
if (should_trim(fm, tsize)) |
sys_trim(fm, 0); |
goto postaction; |
} |
else if (next == fm->dv) { |
size_t dsize = fm->dvsize += psize; |
fm->dv = p; |
set_size_and_pinuse_of_free_chunk(p, dsize); |
goto postaction; |
} |
else { |
size_t nsize = chunksize(next); |
psize += nsize; |
unlink_chunk(fm, next, nsize); |
set_size_and_pinuse_of_free_chunk(p, psize); |
if (p == fm->dv) { |
fm->dvsize = psize; |
goto postaction; |
} |
} |
} |
else |
set_free_with_pinuse(p, psize, next); |
insert_chunk(fm, p, psize); |
check_free_chunk(fm, p); |
goto postaction; |
} |
} |
erroraction: |
USAGE_ERROR_ACTION(fm, p); |
postaction: |
POSTACTION(fm); |
} |
} |
#if !FOOTERS |
#undef fm |
#endif /* FOOTERS */ |
} |
static void* dlcalloc(size_t n_elements, size_t elem_size) { |
void* mem; |
size_t req = 0; |
if (n_elements != 0) { |
req = n_elements * elem_size; |
if (((n_elements | elem_size) & ~(size_t)0xffff) && |
(req / n_elements != elem_size)) |
req = MAX_SIZE_T; /* force downstream failure on overflow */ |
} |
mem = dlmalloc(req); |
if (mem != 0 && calloc_must_clear(mem2chunk(mem))) |
memset(mem, 0, req); |
return mem; |
} |
static void* dlrealloc(void* oldmem, size_t bytes) { |
if (oldmem == 0) |
return dlmalloc(bytes); |
#ifdef REALLOC_ZERO_BYTES_FREES |
if (bytes == 0) { |
dlfree(oldmem); |
return 0; |
} |
#endif /* REALLOC_ZERO_BYTES_FREES */ |
else { |
#if ! FOOTERS |
mstate m = gm; |
#else /* FOOTERS */ |
mstate m = get_mstate_for(mem2chunk(oldmem)); |
if (!ok_magic(m)) { |
USAGE_ERROR_ACTION(m, oldmem); |
return 0; |
} |
#endif /* FOOTERS */ |
return internal_realloc(m, oldmem, bytes); |
} |
} |
static void* dlmemalign(size_t alignment, size_t bytes) { |
return internal_memalign(gm, alignment, bytes); |
} |
static void** dlindependent_calloc(size_t n_elements, size_t elem_size, |
void* chunks[]) { |
size_t sz = elem_size; /* serves as 1-element array */ |
return ialloc(gm, n_elements, &sz, 3, chunks); |
} |
static void** dlindependent_comalloc(size_t n_elements, size_t sizes[], |
void* chunks[]) { |
return ialloc(gm, n_elements, sizes, 0, chunks); |
} |
static void* dlvalloc(size_t bytes) { |
size_t pagesz; |
init_mparams(); |
pagesz = mparams.page_size; |
return dlmemalign(pagesz, bytes); |
} |
static void* dlpvalloc(size_t bytes) { |
size_t pagesz; |
init_mparams(); |
pagesz = mparams.page_size; |
return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); |
} |
static int dlmalloc_trim(size_t pad) { |
int result = 0; |
if (!PREACTION(gm)) { |
result = sys_trim(gm, pad); |
POSTACTION(gm); |
} |
return result; |
} |
static size_t dlmalloc_footprint(void) { |
return gm->footprint; |
} |
static size_t dlmalloc_max_footprint(void) { |
return gm->max_footprint; |
} |
#if !NO_MALLINFO |
struct mallinfo dlmallinfo(void) { |
return internal_mallinfo(gm); |
} |
#endif /* NO_MALLINFO */ |
//void dlmalloc_stats() { |
// internal_malloc_stats(gm); |
//} |
static size_t dlmalloc_usable_size(void* mem) { |
if (mem != 0) { |
mchunkptr p = mem2chunk(mem); |
if (cinuse(p)) |
return chunksize(p) - overhead_for(p); |
} |
return 0; |
} |
static int dlmallopt(int param_number, int value) { |
return change_mparam(param_number, value); |
} |
#endif /* !ONLY_MSPACES */ |
/* ----------------------------- user mspaces ---------------------------- */ |
#if MSPACES |
#endif /* MSPACES */ |
/* -------------------- Alternative MORECORE functions ------------------- */ |
/* |
Guidelines for creating a custom version of MORECORE: |
* For best performance, MORECORE should allocate in multiples of pagesize. |
* MORECORE may allocate more memory than requested. (Or even less, |
but this will usually result in a malloc failure.) |
* MORECORE must not allocate memory when given argument zero, but |
instead return one past the end address of memory from previous |
nonzero call. |
* For best performance, consecutive calls to MORECORE with positive |
arguments should return increasing addresses, indicating that |
space has been contiguously extended. |
* Even though consecutive calls to MORECORE need not return contiguous |
addresses, it must be OK for malloc'ed chunks to span multiple |
regions in those cases where they do happen to be contiguous. |
* MORECORE need not handle negative arguments -- it may instead |
just return MFAIL when given negative arguments. |
Negative arguments are always multiples of pagesize. MORECORE |
must not misinterpret negative args as large positive unsigned |
args. You can suppress all such calls from even occurring by defining |
MORECORE_CANNOT_TRIM, |
As an example alternative MORECORE, here is a custom allocator |
kindly contributed for pre-OSX macOS. It uses virtually but not |
necessarily physically contiguous non-paged memory (locked in, |
present and won't get swapped out). You can use it by uncommenting |
this section, adding some #includes, and setting up the appropriate |
defines above: |
#define MORECORE osMoreCore |
There is also a shutdown routine that should somehow be called for |
cleanup upon program exit. |
#define MAX_POOL_ENTRIES 100 |
#define MINIMUM_MORECORE_SIZE (64 * 1024U) |
static int next_os_pool; |
void *our_os_pools[MAX_POOL_ENTRIES]; |
void *osMoreCore(int size) |
{ |
void *ptr = 0; |
static void *sbrk_top = 0; |
if (size > 0) |
{ |
if (size < MINIMUM_MORECORE_SIZE) |
size = MINIMUM_MORECORE_SIZE; |
if (CurrentExecutionLevel() == kTaskLevel) |
ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); |
if (ptr == 0) |
{ |
return (void *) MFAIL; |
} |
// save ptrs so they can be freed during cleanup |
our_os_pools[next_os_pool] = ptr; |
next_os_pool++; |
ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); |
sbrk_top = (char *) ptr + size; |
return ptr; |
} |
else if (size < 0) |
{ |
// we don't currently support shrink behavior |
return (void *) MFAIL; |
} |
else |
{ |
return sbrk_top; |
} |
} |
// cleanup any allocated memory pools |
// called as last thing before shutting down driver |
void osCleanupMem(void) |
{ |
void **ptr; |
for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) |
if (*ptr) |
{ |
PoolDeallocate(*ptr); |
*ptr = 0; |
} |
} |
*/ |
/* ----------------------------------------------------------------------- |
History: |
V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) |
* Add max_footprint functions |
* Ensure all appropriate literals are size_t |
* Fix conditional compilation problem for some #define settings |
* Avoid concatenating segments with the one provided |
in create_mspace_with_base |
* Rename some variables to avoid compiler shadowing warnings |
* Use explicit lock initialization. |
* Better handling of sbrk interference. |
* Simplify and fix segment insertion, trimming and mspace_destroy |
* Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x |
* Thanks especially to Dennis Flanagan for help on these. |
V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) |
* Fix memalign brace error. |
V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) |
* Fix improper #endif nesting in C++ |
* Add explicit casts needed for C++ |
V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) |
* Use trees for large bins |
* Support mspaces |
* Use segments to unify sbrk-based and mmap-based system allocation, |
removing need for emulation on most platforms without sbrk. |
* Default safety checks |
* Optional footer checks. Thanks to William Robertson for the idea. |
* Internal code refactoring |
* Incorporate suggestions and platform-specific changes. |
Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, |
Aaron Bachmann, Emery Berger, and others. |
* Speed up non-fastbin processing enough to remove fastbins. |
* Remove useless cfree() to avoid conflicts with other apps. |
* Remove internal memcpy, memset. Compilers handle builtins better. |
* Remove some options that no one ever used and rename others. |
V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) |
* Fix malloc_state bitmap array misdeclaration |
V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) |
* Allow tuning of FIRST_SORTED_BIN_SIZE |
* Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. |
* Better detection and support for non-contiguousness of MORECORE. |
Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger |
* Bypass most of malloc if no frees. Thanks To Emery Berger. |
* Fix freeing of old top non-contiguous chunk im sysmalloc. |
* Raised default trim and map thresholds to 256K. |
* Fix mmap-related #defines. Thanks to Lubos Lunak. |
* Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. |
* Branch-free bin calculation |
* Default trim and mmap thresholds now 256K. |
V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) |
* Introduce independent_comalloc and independent_calloc. |
Thanks to Michael Pachos for motivation and help. |
* Make optional .h file available |
* Allow > 2GB requests on 32bit systems. |
* new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>. |
Thanks also to Andreas Mueller <a.mueller at paradatec.de>, |
and Anonymous. |
* Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for |
helping test this.) |
* memalign: check alignment arg |
* realloc: don't try to shift chunks backwards, since this |
leads to more fragmentation in some programs and doesn't |
seem to help in any others. |
* Collect all cases in malloc requiring system memory into sysmalloc |
* Use mmap as backup to sbrk |
* Place all internal state in malloc_state |
* Introduce fastbins (although similar to 2.5.1) |
* Many minor tunings and cosmetic improvements |
* Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK |
* Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS |
Thanks to Tony E. Bennett <tbennett@nvidia.com> and others. |
* Include errno.h to support default failure action. |
V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) |
* return null for negative arguments |
* Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com> |
* Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' |
(e.g. WIN32 platforms) |
* Cleanup header file inclusion for WIN32 platforms |
* Cleanup code to avoid Microsoft Visual C++ compiler complaints |
* Add 'USE_DL_PREFIX' to quickly allow co-existence with existing |
memory allocation routines |
* Set 'malloc_getpagesize' for WIN32 platforms (needs more work) |
* Use 'assert' rather than 'ASSERT' in WIN32 code to conform to |
usage of 'assert' in non-WIN32 code |
* Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to |
avoid infinite loop |
* Always call 'fREe()' rather than 'free()' |
V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) |
* Fixed ordering problem with boundary-stamping |
V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) |
* Added pvalloc, as recommended by H.J. Liu |
* Added 64bit pointer support mainly from Wolfram Gloger |
* Added anonymously donated WIN32 sbrk emulation |
* Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen |
* malloc_extend_top: fix mask error that caused wastage after |
foreign sbrks |
* Add linux mremap support code from HJ Liu |
V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) |
* Integrated most documentation with the code. |
* Add support for mmap, with help from |
Wolfram Gloger (Gloger@lrz.uni-muenchen.de). |
* Use last_remainder in more cases. |
* Pack bins using idea from colin@nyx10.cs.du.edu |
* Use ordered bins instead of best-fit threshhold |
* Eliminate block-local decls to simplify tracing and debugging. |
* Support another case of realloc via move into top |
* Fix error occuring when initial sbrk_base not word-aligned. |
* Rely on page size for units instead of SBRK_UNIT to |
avoid surprises about sbrk alignment conventions. |
* Add mallinfo, mallopt. Thanks to Raymond Nijssen |
(raymond@es.ele.tue.nl) for the suggestion. |
* Add `pad' argument to malloc_trim and top_pad mallopt parameter. |
* More precautions for cases where other routines call sbrk, |
courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). |
* Added macros etc., allowing use in linux libc from |
H.J. Lu (hjl@gnu.ai.mit.edu) |
* Inverted this history list |
V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) |
* Re-tuned and fixed to behave more nicely with V2.6.0 changes. |
* Removed all preallocation code since under current scheme |
the work required to undo bad preallocations exceeds |
the work saved in good cases for most test programs. |
* No longer use return list or unconsolidated bins since |
no scheme using them consistently outperforms those that don't |
given above changes. |
* Use best fit for very large chunks to prevent some worst-cases. |
* Added some support for debugging |
V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) |
* Removed footers when chunks are in use. Thanks to |
Paul Wilson (wilson@cs.texas.edu) for the suggestion. |
V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) |
* Added malloc_trim, with help from Wolfram Gloger |
(wmglo@Dent.MED.Uni-Muenchen.DE). |
V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) |
V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) |
* realloc: try to expand in both directions |
* malloc: swap order of clean-bin strategy; |
* realloc: only conditionally expand backwards |
* Try not to scavenge used bins |
* Use bin counts as a guide to preallocation |
* Occasionally bin return list chunks in first scan |
* Add a few optimizations from colin@nyx10.cs.du.edu |
V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) |
* faster bin computation & slightly different binning |
* merged all consolidations to one part of malloc proper |
(eliminating old malloc_find_space & malloc_clean_bin) |
* Scan 2 returns chunks (not just 1) |
* Propagate failure in realloc if malloc returns 0 |
* Add stuff to allow compilation on non-ANSI compilers |
from kpv@research.att.com |
V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) |
* removed potential for odd address access in prev_chunk |
* removed dependency on getpagesize.h |
* misc cosmetics and a bit more internal documentation |
* anticosmetics: mangled names in macros to evade debugger strangeness |
* tested on sparc, hp-700, dec-mips, rs6000 |
with gcc & native cc (hp, dec only) allowing |
Detlefs & Zorn comparison study (in SIGPLAN Notices.) |
Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) |
* Based loosely on libg++-1.2X malloc. (It retains some of the overall |
structure of old version, but most details differ.) |
*/ |
/programs/develop/libraries/libGUI/SRC/parent_window.inc |
---|
0,0 → 1,142 |
/* |
create parent of window |
*/ |
#define PARENT_WINDOW_DEFAULT_SIZEX 320 |
#define PARENT_WINDOW_DEFAULT_SIZEY 200 |
#define PARENT_WINDOW_BORDER_WIDTH 5; |
void gui_get_screen_parameters(void) |
{ |
int value; |
value=(int)gui_ksys_get_screen_bits_per_pixel(); |
screen.bits_per_pixel=(char)value; |
screen.bytes_per_pixel=screen.bits_per_pixel >> 3; |
screen.skin_height=gui_ksys_get_skin_height(); |
screen.x=PARENT_WINDOW_BORDER_WIDTH; |
screen.y=screen.skin_height; |
value=gui_ksys_get_screen_size(); |
screen.display_size_y=value & 0xffff; |
screen.display_size_y=value >> 16; |
} |
void gui_draw_window(parent_t *window) |
{ |
DWORD flag; |
flag=3; |
flag=flag<<24; |
flag +=0xaabbcc; |
gui_ksys_begin_draw_window(); |
gui_ksys_draw_window(window->ctrl_x,window->ctrl_y,window->ctrl_sizex,window->ctrl_sizey,flag); |
gui_ksys_finish_draw_window(); |
} |
//--------------------------------------------------------------------------------- |
// create window parent |
//--------------------------------------------------------------------------------- |
void* CreateWindow(void) |
{ |
struct HEADERPARENT *WindowParent; |
WindowParent=malloc(sizeof(parent_t)); |
WindowParent->message=malloc(sizeof(gui_message_t)); |
WindowParent->control_for_callback_function=malloc(sizeof(DWORD)*MAX_CALLBACKS); |
WindowParent->callback_for_control_callback=malloc(sizeof(DWORD)*MAX_CALLBACKS); |
WindowParent->main_parent=(DWORD*)WindowParent; |
WindowParent->global_active_control_for_keys=(DWORD*)NULL; |
WindowParent->control_for_callback_function[0]=(DWORD*)NULL; |
WindowParent->number_callbacks=0; |
WindowParent->child_bk=(DWORD*)NULL; |
WindowParent->active_control_for_keys=(DWORD*)NULL; |
WindowParent->active_control_for_mouse=(DWORD*)NULL; |
WindowParent->ctrl_x=0x0; |
WindowParent->ctrl_y=0x0; |
WindowParent->ctrl_sizex=PARENT_WINDOW_DEFAULT_SIZEX; |
WindowParent->ctrl_sizey=PARENT_WINDOW_DEFAULT_SIZEY; |
WindowParent->callback=(DWORD*)NULL;//no callbacks yet |
WindowParent->timer=(DWORD*)NULL;//no timers yet |
WindowParent->flags=0; |
WindowParent->flags=WindowParent->flags | FLAG_SHOW_CONTROL; |
WindowParent->flags=WindowParent->flags | FLAG_FOCUSE_INPUT_SUPPOROTE; |
WindowParent->number_timers_for_controls=0; |
WindowParent->timer_bk=(DWORD*)NULL; |
WindowParent->timer_fd=(DWORD*)NULL; |
WindowParent->callback=(DWORD*)NULL; |
WindowParent->calev_bk=(DWORD*)NULL; |
WindowParent->calev_fd=(DWORD*)NULL; |
WindowParent->IDL_func=(DWORD*)NULL; |
//--------------------------------------------------------------------------------- |
//---------------------------platform depended part of code------------------------ |
//--------------------------------------------------------------------------------- |
//create and initialize screen buffer |
gui_get_screen_parameters(); |
//by default draw output to the screen |
screen.draw_output=DRAW_OUTPUT_SCREEN; |
//calculate size of client's arrea |
screen.size_x=WindowParent->ctrl_sizex-9; |
screen.size_y=WindowParent->ctrl_sizey-screen.skin_height-4; |
//---------------------------------------------------------------------------------- |
ID=0; |
#ifdef DEBUG |
printf("\ncreated parent window %d",(DWORD)WindowParent); |
#endif |
return(WindowParent); |
} |
//--------------------------------------------------------------------------------- |
// create window parent |
//--------------------------------------------------------------------------------- |
void SetWindowSizeRequest(parent_t *WindowParent,int size_x,int size_y) |
{ |
static int x,y,sizex,sizey; |
//--------------------------------------------------------------------------------- |
//---------------------------platform depended part of code------------------------ |
//--------------------------------------------------------------------------------- |
x=WindowParent->ctrl_x; |
y=WindowParent->ctrl_y; |
sizex=size_x; |
sizey=size_y; |
gui_ksys_set_position_and_size_window(x,y,sizex,sizey); |
//--------------------------------------------------------------------------------- |
WindowParent->ctrl_sizex=sizex; |
WindowParent->ctrl_sizey=sizey; |
screen.size_x=WindowParent->ctrl_sizex-9; |
screen.size_y=WindowParent->ctrl_sizey-screen.skin_height-4; |
#ifdef DEBUG |
printf("\nwindow resized new sizex=%d sizey=%d", |
WindowParent->ctrl_sizex, |
WindowParent->ctrl_sizey); |
#endif |
} |
void GetNewWindowSizePos(parent_t *WindowParent) |
{ |
static process_table_t procinfo; |
gui_ksys_get_current_process_information(&procinfo); |
WindowParent->ctrl_x=(DWORD)procinfo.winx_start; |
WindowParent->ctrl_y=(DWORD)procinfo.winy_start; |
WindowParent->ctrl_sizex=(DWORD)procinfo.winx_size; |
WindowParent->ctrl_sizey=(DWORD)procinfo.winy_size; |
//get screen parameters again |
gui_get_screen_parameters(); |
} |
/programs/develop/libraries/libGUI/SRC/stdarg.h |
---|
0,0 → 1,8 |
typedef char *va_list; |
#define _roundsize(n) ( (sizeof(n) + 3) & ~3 ) |
#define va_start(ap,v) (ap = (va_list)&v+_roundsize(v)) |
#define va_arg(ap,t) ( *(t *)((ap += _roundsize(t)) - _roundsize(t)) ) |
#define va_end(ap) (ap = (va_list)0) |
/programs/develop/libraries/libGUI/SRC/stdio.h |
---|
0,0 → 1,4 |
+ |
+ |
/programs/develop/libraries/libGUI/SRC/stdio.inc |
---|
0,0 → 1,792 |
/* |
function for format output to the string |
*/ |
static int formatted_double_to_string(long double number,int format1,int format2,char *s) |
{ |
/* |
double n; |
double nbefor; |
double nafter; |
double v,v2; |
long intdigit; |
long beforpointdigit; |
long div; |
int i; |
int pos; |
int size; |
int fmt1; |
int fmt2; |
long mul; |
static char buf[200]; |
size=(int)s; |
n=(double)number; |
if (n<0) {*s='-';s++;n=-n;} |
fmt1=format1; |
fmt2=format2; |
if (fmt2>18) {fmt2=18;} //maximum of size long long type |
//clear array befor output |
for(i=0;i<=200;i++) {buf[i]=0;} |
if ((fmt1>=0) && (n<1)) |
{ //formatted output if 0<=n<1 |
mul=1; |
for(i=0;i<fmt2;i++) |
{n=n*10;mul=mul*10;} |
n=n*10; |
n=ceil(n); |
intdigit=floor(n); |
//intdigit=n; |
intdigit=(intdigit/10); |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt2-1;i++) |
{ |
div=intdigit/mul; |
buf[pos]=(char)div; |
pos++; |
intdigit=intdigit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
} |
buf[pos]=(char)intdigit; |
*s='0';s++; |
*s='.';s++; |
for(i=0;i<format2;i++) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
else {*s='0';} |
s++; |
} |
} |
else |
{ //if n>=1 |
//v=floorf(n+0.00000000000001); |
beforpointdigit=floor(n+0.00000000000001); |
//beforpointdigit=n; |
nbefor=beforpointdigit; |
nafter=n-nbefor; |
//print part of number befor point |
mul=1; |
for(i=0;i<200-2;i++) |
{ |
mul=mul*10; |
if ((beforpointdigit/mul)==0) {fmt1=i+1;break;} |
} |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt1-1;i++) |
{ |
div=beforpointdigit/mul; |
buf[pos]=(char)div; |
pos++; |
beforpointdigit=beforpointdigit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
} |
buf[pos]=(char)beforpointdigit; |
for(i=0;i<fmt1;i++) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
s++; |
} |
//print part of number after point |
mul=1; |
for(i=0;i<fmt2;i++) |
{nafter=nafter*10;mul=mul*10;} |
nafter=nafter*10; |
nafter=ceil(nafter); |
intdigit=floor(nafter); |
//intdigit=nafter; |
intdigit=intdigit/10; |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt2-1;i++) |
{ |
div=intdigit/mul; |
buf[pos]=(char)div; |
pos++; |
intdigit=intdigit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
} |
buf[pos]=(char)intdigit; |
*s='.';s++; |
for(i=0;i<format2;i++) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
else {*s='0';} |
s++; |
} |
} |
size=(int)s-size; |
return(size); |
*/ |
} |
static int formatted_long_to_string(long long number,int fmt1,char *s) |
{ |
int i; |
int pos; |
int fmt; |
int size; |
int difference_pos; |
long digit; |
long mul; |
long div; |
static char buf[200]; |
//clear array befor output |
for(i=0;i<200;i++) {buf[i]=0;} |
digit=number; |
size=(int)s; |
if (digit<0) {*s='-';s++;digit=-digit;} |
if (digit==0) {*s='0';s++;goto end;} |
mul=1; |
for(i=0;i<200-2;i++) |
{ |
mul=mul*10; |
if ((digit/mul)==0) {fmt=i+1;break;} |
} |
difference_pos=i+1; |
pos=0; |
mul=mul/10; |
for(i=0;i<fmt-1;i++) |
{ |
div=digit/mul; |
buf[pos]=(char)div; |
pos++; |
digit=digit-div*mul; |
mul=mul/10; |
if (mul==1) break; |
} |
buf[pos]=(char)digit; |
if (fmt1>=difference_pos) fmt=fmt1; |
else |
fmt=difference_pos; |
for(i=0;i<fmt;i++) |
{ |
if (i<difference_pos) |
{ |
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];} |
} |
else |
{ |
*s=' '; |
} |
s++; |
} |
end: |
size=(int)s-size; |
return(size); |
} |
static int formatted_hex_to_string(long long number,int fmt1,char flag_register,char *s) |
{ |
long n; |
int i,pos; |
int fmt; |
long size; |
int difference_pos; |
static char xdigs_lower[]="0123456789abcdef"; |
static char xdigs_upper[]="0123456789ABCDEF"; |
static char buf[200]; |
n=(long)number; |
size=(int)s; |
if (n<0) {*s='-';s++;n=-n;} |
if (n==0) {*s='0';s++;goto end;} |
for(i=0;i<200;i++) {buf[i]=0;} |
i=0; |
if (flag_register==0) |
{ |
while (n>0) |
{ |
buf[i]=xdigs_lower[n & 15]; |
n=n>>4; |
i++; |
} |
} |
else |
{ |
while (n>0) |
{ |
buf[i]=xdigs_upper[n & 15]; |
n=n>>4; |
i++; |
} |
} |
pos=i; |
difference_pos=i; |
for(i=pos-1;i>=0;i--) |
{ |
*s=buf[i]; |
s++; |
} |
if (fmt1-difference_pos>0) |
{ |
for(i=difference_pos+1;i<=fmt1;i++) |
{ |
*s=' '; |
s++; |
} |
} |
end:size=(int)s-size; |
return(size); |
} |
static int formatted_octa_to_string(long long number,int fmt1,char flag_register,char *s) |
{ |
long n; |
int i,pos; |
int fmt; |
long size; |
int difference_pos; |
static char xdigs_lower[16]="012345678"; |
static char buf[200]; |
n=number; |
size=(int)s; |
if (n<0) {*s='-';s++;n=-n;} |
if (n==0) {*s='0';s++;goto end;} |
for(i=0;i<200;i++) {buf[i]=0;} |
i=0; |
if (flag_register==0) |
{ |
while (n>0) |
{ |
buf[i]=xdigs_lower[n & 7]; |
n=n>>3; |
i++; |
} |
} |
pos=i; |
difference_pos=i; |
for(i=pos-1;i>=0;i--) |
{ |
*s=buf[i]; |
s++; |
} |
if (fmt1-difference_pos>0) |
{ |
for(i=difference_pos+1;i<=fmt1;i++) |
{ |
*s=' '; |
s++; |
} |
} |
end:size=(int)s-size; |
return(size); |
} |
static int format_print(char *dest, size_t maxlen,const char *fmt0, va_list argp) |
{ |
int i,j,k; |
int length; |
int fmt1,fmt2,stepen; |
size_t pos,posc; |
long long intdigit; |
long double doubledigit; |
float floatdigit; |
const char *fmt,*fmtc; |
char *s; |
char *str; |
static char buffmt1[30]; |
static char buffmt2[30]; |
static char buf[1024]; |
char format_flag; |
char flag_point; |
char flag_noformat; |
char flag_long; |
char flag_unsigned; |
char flag_register; |
char flag_plus; |
fmt=fmt0; |
s=dest; |
pos=0; |
maxlen--; |
if (maxlen<=0) return(0); |
while(pos<maxlen) |
{ |
if (*fmt=='%') |
{ |
if (*(fmt+1)=='%') |
{ |
*s='%'; |
s++; |
fmt=fmt+2; |
pos++; |
goto exit_check; |
} |
//checking to containg format in the string |
fmtc=fmt; |
posc=pos; |
format_flag=0; |
flag_long=0; |
flag_unsigned=0; |
flag_register=0; |
flag_plus=0; |
while((*fmtc!='\0') || (*fmtc!=0)) |
{ |
fmtc++; |
posc++; |
switch(*fmtc) |
{ |
case 'c': |
case 'C': |
format_flag=1; |
break; |
case 'd': |
case 'D': |
case 'i': |
case 'I': |
format_flag=1; |
break; |
case 'e': |
format_flag=1; |
break; |
case 'E': |
format_flag=1; |
flag_long=1; |
break; |
case 'f': |
format_flag=1; |
break; |
case 'F': |
format_flag=1; |
flag_long=1; |
break; |
case 'g': |
format_flag=1; |
break; |
case 'G': |
format_flag=1; |
flag_long=1; |
break; |
case 'l': |
flag_long=1; |
break; |
case 'L': |
flag_long=2; |
break; |
case 'o': |
format_flag=1; |
break; |
case 's': |
case 'S': |
format_flag=1; |
break; |
case 'u': |
case 'U': |
format_flag=1; |
flag_unsigned=1; |
break; |
case 'x': |
format_flag=1; |
break; |
case 'X': |
flag_register=1; |
format_flag=1; |
break; |
case 'z': |
case 'Z': |
format_flag=1; |
flag_unsigned=1; |
break; |
case '+': |
flag_plus=1; |
break; |
default:; |
} |
if ((*fmtc=='%') || (*fmtc==' ')) break; |
if (format_flag==1) break; |
} |
if (format_flag==0) |
{ |
*s=*fmt; |
fmt++; |
s++; |
pos++; |
} |
else |
{ |
if ((posc-pos)==1) |
{//simbols % and format simbol near tothere(for example %c ) |
fmt=fmtc+1; |
switch(*fmtc) |
{ |
case 'c': |
case 'C': |
if ((pos+1)<maxlen) |
{ |
//*s=(int)va_arg(argp,char*); |
*s=*((char *)argp); |
argp=argp+4; |
*s++;pos++; |
} |
break; |
case 's': |
case 'S': |
str=va_arg(argp,char*); |
length=strlen(str); |
if ((pos+length)<maxlen) |
{ |
memmove(s,str,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'd': |
case 'D': |
case 'i': |
case 'I': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
//intdigit=*((long*)argp); |
//argp=argp+4; |
if ((intdigit>0) && (flag_plus==1) && (pos+1<maxlen)) |
{ |
*s='+'; |
s++; |
pos++; |
} |
length=formatted_long_to_string(intdigit,0,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'o': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
//intdigit=*((long int *)argp); |
//argp=argp+4; |
length=formatted_octa_to_string(intdigit,0,flag_register,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'u': |
case 'U': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long int);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
if (flag_unsigned==1) { |
if (intdigit<0) {intdigit=-intdigit;} |
} |
length=formatted_long_to_string(intdigit,0,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'x': |
case 'X': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
//intdigit=*((long int *)argp); |
//argp=argp+4; |
length=formatted_hex_to_string(intdigit,0,flag_register,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'z': |
case 'Z': |
intdigit=va_arg(argp,size_t); |
if (flag_unsigned==1) { |
if (intdigit<0) {intdigit=-intdigit;} |
} |
length=formatted_long_to_string(intdigit,0,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
default:; |
} |
} |
else |
{ |
fmt++; |
flag_point=0; |
flag_noformat=0; |
fmt1=0; |
fmt2=0; |
j=0; |
k=0; |
for(i=pos+1;i<posc;i++) |
{ |
switch(*fmt) |
{ |
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
if (flag_point==0) |
{ |
buffmt1[j]=*fmt-'0'; |
j++; |
} |
else |
{ |
buffmt2[k]=*fmt-'0'; |
k++; |
} |
break; |
case '.': |
flag_point=1; |
break; |
case 'l': |
case 'L': |
break; |
case '+': |
break; |
default:flag_noformat=1; |
} |
if (flag_noformat==1) break; |
fmt++; |
} |
if (flag_noformat==0) |
{ |
stepen=1; |
for(i=j-1;i>=0;i--) |
{ |
fmt1=fmt1+buffmt1[i]*stepen; |
stepen=stepen*10; |
} |
stepen=1; |
for(i=k-1;i>=0;i--) |
{ |
fmt2=fmt2+buffmt2[i]*stepen; |
stepen=stepen*10; |
} |
switch(*fmtc) |
{ |
case 'f': |
case 'F': |
if (flag_long==0) {doubledigit=va_arg(argp,double);} |
if (flag_long>=1) {doubledigit=va_arg(argp,long double);} |
//doubledigit=*((double *)argp); |
//sargp=argp+8; |
length=formatted_double_to_string(doubledigit,fmt1,fmt2,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'd': |
case 'D': |
case 'i': |
case 'I': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
if ((intdigit>0) && (flag_plus==1) && (pos+1<maxlen)) |
{ |
*s='+'; |
s++; |
pos++; |
} |
length=formatted_long_to_string(intdigit,fmt1,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'o': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
length=formatted_octa_to_string(intdigit,fmt1,flag_register,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'u': |
case 'U': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long int);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
if (flag_unsigned==1) { |
if (intdigit<0) {intdigit=-intdigit;} |
} |
length=formatted_long_to_string(intdigit,fmt1,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'x': |
case 'X': |
if (flag_long==0) {intdigit=va_arg(argp,int);} |
if (flag_long==1) {intdigit=va_arg(argp,long int);} |
if (flag_long==2) {intdigit=va_arg(argp,long long);} |
length=formatted_hex_to_string(intdigit,fmt1,flag_register,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
case 'z': |
case 'Z': |
intdigit=va_arg(argp,size_t); |
if (flag_unsigned==1) { |
if (intdigit<0) {intdigit=-intdigit;} |
} |
length=formatted_long_to_string(intdigit,fmt1,buf); |
if ((pos+length)<maxlen) |
{ |
memmove(s,buf,length); |
s=s+length;pos=pos+length; |
} |
break; |
default:; |
} |
} |
fmt=fmtc+1; |
} |
} |
} |
else |
{ |
if (*fmt=='\0') {break;} |
*s=*fmt; |
fmt++; |
s++; |
pos++; |
} |
exit_check:; |
} |
*s='\0'; |
return(pos); |
} |
static char* dllname="/sys/lib/console.obj"; |
int console_init_status=0; |
static char* imports[] = {"con_init","con_printf","con_exit"}; |
static char* caption = "libGUI debug Console"; |
static void (stdcall *con_init)( |
DWORD wnd_width, |
DWORD wnd_height, |
DWORD scr_width, |
DWORD scr_height, |
const char* title); |
static void (cdecl *con_printf)(const char* format,...); |
static void (stdcall *con_exit)(DWORD bCloseWindow); |
static void printf_link(import_t *exp, char** imports) |
{ |
con_init = (void (stdcall *)(DWORD , DWORD, DWORD, DWORD, const char*)) |
gui_cofflib_getproc(exp, imports[0]); |
con_printf = (void (cdecl *)(const char*,...)) |
gui_cofflib_getproc(exp, imports[1]); |
con_exit = (void (stdcall *)(DWORD)) |
gui_cofflib_getproc(exp, imports[2]); |
} |
static int init_console(void) |
{ |
import_t *hDll; |
if((hDll = (import_t*)gui_ksys_load_dll(dllname)) == 0) |
{ |
gui_debug_out_str("can't load lib\n"); |
return 1; |
} |
printf_link(hDll, imports); |
con_init(78,26,78,200, caption); |
return(0); |
} |
static int printf(const char *format,...) |
{ |
int i; |
int printed_simbols; |
va_list arg; |
char *s; |
va_start(arg,format); |
s=malloc(4096); |
printed_simbols=format_print(s,4096,format,arg); |
if (console_init_status==0) |
{ |
i=init_console(); |
console_init_status=1; |
} |
con_printf("%s",s); |
free(s); |
return(printed_simbols); |
} |
/programs/develop/libraries/libGUI/SRC/stdlib.h |
---|
0,0 → 1,9 |
/* |
some standart libC helper functions |
*/ |
static void* malloc(DWORD size); |
static void free(void *memory); |
static void* realloc(void *old_mem,DWORD new_size); |
static void exit(int c); |
/programs/develop/libraries/libGUI/SRC/stdlib.inc |
---|
0,0 → 1,24 |
/* |
some standart libC functions |
*/ |
/* |
static void* malloc(DWORD size) |
{ |
return dlmalloc(size); |
} |
static void free(void *memory) |
{ |
dlfree(memory); |
} |
static void* realloc(void *old_mem,DWORD new_size) |
{ |
return dlrealloc(old_mem,new_size); |
} |
*/ |
static void exit(int c) |
{ |
gui_ksys_exit(c); |
} |
/programs/develop/libraries/libGUI/SRC/string.h |
---|
0,0 → 1,17 |
/* |
some libC function working with memory |
*/ |
static void *memmove(void *dst,const void *src,size_t length); |
static void *memset(const void *dst, int c, size_t length); |
static size_t strlen(const char *s); |
static char* strchr(const char *string, int c); |
static char* strrchr(const char *string, int c); |
static char* strstr(const char *s1,const char *s2); |
static int strcmp(const char*,const char*); |
static int strncmp(const char* string1, const char* string2,size_t count); |
static int vsnprintf(char *dest, size_t size,const char *format,va_list ap); |
static int cdecl snprintf(char *dest, size_t size, const char *format,...); |
static int cdecl sprintf(char *dest,const char *format,...); |
/programs/develop/libraries/libGUI/SRC/string.inc |
---|
0,0 → 1,163 |
/* |
some libC function working with memory |
*/ |
static void *memmove(void *dst,const void *src,size_t length) |
{ |
void *value; |
if (length & 3) |
{//length not aligned in 4 bytes use reb movsb |
__asm__ __volatile__( |
"movl %%edi,%%eax\n\t" |
"cld\n\t" |
"rep\n\t" |
"movsb" |
:"=D"(value) |
:"c"(length),"S"(src),"D"(dst) |
:"eax"); |
} |
else |
{//length aligned in 4 bytes use rep movsd |
length=length >> 2;//length=length/4 |
__asm__ __volatile__( |
"movl %%edi,%%eax\n\t" |
"cld\n\t" |
"rep\n\t" |
"movsd" |
:"=D"(value) |
:"c"(length),"S"(src),"D"(dst) |
:"eax"); |
} |
return(value); |
} |
static void *memset(const void *dst, int c, size_t length) |
{ |
unsigned char cfill; |
cfill=c; |
while(length) |
{ |
*(char*)dst=c; |
dst=(char*)dst+1; |
length--; |
} |
return((void*)1); |
} |
static size_t strlen(const char *s) |
{ |
size_t i; |
i=0; |
while(*s!='\0') |
{ |
i++; |
s++; |
} |
return(i); |
} |
static char* strchr(const char *string, int c) |
{ |
while(*string!='\0') |
{ |
if (*string==(char)c) return((char*)string); |
string++; |
} |
return(NULL); |
} |
static char* strrchr(const char *string, int c) |
{ |
char *s; |
int i,j; |
s=(char*)string; |
while(*s!='\0') {s++;} |
j=(int)(s-string); |
s--; |
for(i=0;i<j;i++) |
{ |
if (*s==(char)c) return(s); |
s--; |
} |
return(NULL); |
} |
static char* strstr(const char *s1,const char *s2) |
{ |
char *s; |
int i,j,len1,len2; |
len2=strlen(s2); |
if (len2==0) return((char*)s1); |
len1=strlen(s1); |
for(i=0;i<len1-len2+1;i++) |
{ |
if (s1[i]==s2[0]) |
{ |
for(j=0;j<len2;j++) |
{ |
if (s1[i+j]!=s2[j]) break; |
} |
if (j==len2) return((char*)(s1+i)); |
} |
} |
return(NULL); |
} |
static int strcmp(const char* string1, const char* string2) |
{ |
while (1) |
{ |
if (*string1<*string2) |
return -1; |
if (*string1>*string2) |
return 1; |
if (*string1=='\0') |
return 0; |
string1++; |
string2++; |
} |
} |
static int strncmp(const char* string1, const char* string2,size_t count) |
{ |
while(count>0 && *string1==*string2) |
{ |
if (*string1) return 0; |
++string1; |
++string2; |
--count; |
} |
if(count) return (*string1 - *string2); |
return 0; |
} |
static int sprintf(char *dest,const char *format,...) |
{ |
va_list arg; |
va_start (arg, format); |
return format_print(dest,strlen(dest), format, arg); |
} |
static int snprintf(char *dest, size_t size,const char *format,...) |
{ |
va_list arg; |
va_start (arg, format); |
return format_print(dest,size, format, arg); |
} |
static int vsnprintf(char *dest, size_t size,const char *format,va_list ap) |
{ |
return format_print(dest,size, format, ap); |
} |
/programs/develop/libraries/libGUI/SRC/types.h |
---|
0,0 → 1,13 |
/* |
some used types |
*/ |
#define NULL (void*)0 |
typedef unsigned int DWORD; |
typedef unsigned char BYTE; |
typedef unsigned short int WORD; |
typedef unsigned int size_t; |
//for win compilers |
#define stdcall __stdcall |
#define cdecl __cdecl |
/programs/develop/libraries/libGUI/SRC |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/libGUI/examples/src/button.c |
---|
0,0 → 1,70 |
/* |
test libGUI library |
*/ |
#include "stdarg.h" |
#include "libGUI.h" |
#include "stdio.h" |
#include "stdlib.h" |
#include "string.h" |
#define FALSE 0 |
#define TRUE 1 |
void callback_func_delete_window(header_t *control,void *data) |
{ |
QuitLibGUI((parent_t*)control); |
} |
void callback_func1(header_t *control,void *data) |
{ |
printf("\nentry in button"); |
} |
void callback_func2(header_t *control,void *data) |
{ |
printf("\nbutton pressed"); |
} |
void callback_func3(header_t *control,void *data) |
{ |
printf("\nbutton released"); |
} |
void callback_func4(header_t *control,void *data) |
{ |
printf("\nleave button"); |
} |
int main(int argc, char *argv[]) |
{ |
parent_t *window; |
gui_callback_t *id1,*id2,*id3,*id4; |
gui_button_data_t button_data; |
gui_button_t *button; |
//load libGUI library |
LoadLibGUI(NULL); |
//create main window |
window=CreateWindow(); |
SetWindowSizeRequest(window,90,60); |
//create button |
button_data.x=5; |
button_data.y=5; |
button_data.width=70; |
button_data.height=20; |
//create button with text |
button=CreateButtonWithText(&button_data,"Click my!"); |
//set callback functions for button close window |
SetCallbackFunction(window,DELETE_EVENT,&callback_func_delete_window,NULL); |
//set callback functions for button |
id1=SetCallbackFunction(button,BUTTON_ENTER_EVENT,&callback_func1,NULL); |
id2=SetCallbackFunction(button,BUTTON_PRESSED_EVENT,&callback_func2,NULL); |
id3=SetCallbackFunction(button,BUTTON_RELEASED_EVENT,&callback_func3,NULL); |
id4=SetCallbackFunction(button,BUTTON_LEAVE_EVENT,&callback_func4,NULL); |
//pack button in window |
PackControls(window,button); |
//start main libGUI loop |
LibGUImain(window); |
} |
/programs/develop/libraries/libGUI/examples/src/image.c |
---|
0,0 → 1,52 |
/* |
test libGUI library |
*/ |
#include "stdarg.h" |
#include "libGUI.h" |
#include "stdlib.h" |
#include "stdio.h" |
void callback_func_delete_window(header_t *control,void *data) |
{ |
QuitLibGUI((parent_t*)control); |
} |
int main(int argc, char *argv[]) |
{ |
parent_t *window; |
gui_image_data_t imdata; |
gui_image_t *image; |
int i,j; |
unsigned int *img; |
//load libGUI library |
LoadLibGUI(NULL);//use default system path to library |
//create main window |
window=CreateWindow(); |
//change window size |
SetWindowSizeRequest(window,220,142); |
//set callback function for close window button |
SetCallbackFunction(window,DELETE_EVENT,&callback_func_delete_window,NULL); |
//create image |
imdata.x=5; |
imdata.y=5; |
imdata.width=200; |
imdata.height=100; |
imdata.bits_per_pixel=32;//bits per pixel |
image=CreateImage(&imdata); |
img=(unsigned int*)image->img; |
//generate 32 bits image |
for(i=0;i<GetControlSizeY(image);i++) |
{ |
for(j=0;j<GetControlSizeX(image);j++) |
{ |
*img=100*(i*i+j*j-i*3+2*j); |
img++; |
} |
} |
//pack image in window |
PackControls(window,image); |
//start main libGUI loop |
LibGUImain(window); |
} |
/programs/develop/libraries/libGUI/examples/src/progress_bar.c |
---|
0,0 → 1,66 |
/* |
test libGUI library |
*/ |
#include "stdarg.h" |
#include "libGUI.h" |
#include "string.h" |
void callback_func_delete_window(header_t *control,void *data) |
{ |
QuitLibGUI((parent_t*)control); |
} |
void ProgressBarCallback(void *data) |
{ |
gui_progress_bar_t *progress_bar; |
int progress; |
static char txt[16]; |
progress_bar=(gui_progress_bar_t*)data; |
progress_bar->progress+=0.01;//incrase progress |
if (progress_bar->progress>1.0) progress_bar->progress=0.0; |
//calculate progress level in % |
progress=progress_bar->progress*100; |
snprintf(txt,16,"progress %d%%",progress); |
//set text for progress bar |
ProgressBarSetText(progress_bar,txt); |
} |
int main(int argc, char *argv[]) |
{ |
parent_t *window; |
gui_progress_bar_data_t progress_bar_data; |
gui_progress_bar_t *progress_bar; |
gui_timer_t *timer; |
//load libGUI library |
LoadLibGUI(NULL);//use default system path to library |
//create main window |
window=CreateWindow(); |
//change size of main window |
SetWindowSizeRequest(window,320,57); |
//set callback function for button close window |
SetCallbackFunction(window,DELETE_EVENT,&callback_func_delete_window,NULL); |
//create progress bar |
progress_bar_data.x=5; |
progress_bar_data.y=5; |
progress_bar_data.width=300; |
progress_bar_data.height=25; |
progress_bar_data.progress=0.0; |
progress_bar=CreateProgressBar(&progress_bar_data); |
//create timer for update progress level each 50 millisecunds |
timer=SetTimerCallbackForFunction(window,5,&ProgressBarCallback,progress_bar); |
//pack progress bar in window |
PackControls(window,progress_bar); |
//update progress bar automatically each 50 millisecund |
SetProgressBarPulse(progress_bar,5); |
//call main libGUI loop |
LibGUImain(window); |
} |
/programs/develop/libraries/libGUI/examples/src/scroll_bar.c |
---|
0,0 → 1,76 |
/* |
test libGUI library |
*/ |
#include "stdarg.h" |
#include "libGUI.h" |
#include "stdio.h" |
#define FALSE 0 |
#define TRUE 1 |
void callback_func_delete_window(header_t *control,void *data) |
{ |
printf("\nlibGUI quit..."); |
QuitLibGUI((parent_t*)control); |
} |
void ScrollStateH(header_t *control,void *data) |
{ |
gui_scroll_bar_t *hsc; |
hsc=(gui_scroll_bar_t*)control; |
printf("\nhorizontal ruler position %d%%",(int)(hsc->ruller_pos*100)); |
} |
void ScrollStateV(header_t *control,void *data) |
{ |
gui_scroll_bar_t *vsc; |
vsc=(gui_scroll_bar_t*)control; |
printf("\nvertical ruler position %d%%",(int)(vsc->ruller_pos*100)); |
} |
int main(int argc, char *argv[]) |
{ |
parent_t *window; |
gui_callback_t *id1,*id2; |
gui_scroll_bar_data_t horizontal_sbar_data; |
gui_scroll_bar_data_t vertical_sbar_data; |
gui_scroll_bar_t *ScrollBarH; |
gui_scroll_bar_t *ScrollBarV; |
//load libGUI library |
LoadLibGUI(NULL);//use default system path to library |
//create main window |
window=CreateWindow(); |
//change size of window |
SetWindowSizeRequest(window,270,207); |
//create horizontal scroll bar |
horizontal_sbar_data.x=5; |
horizontal_sbar_data.y=5; |
horizontal_sbar_data.width=250; |
horizontal_sbar_data.height=16; |
horizontal_sbar_data.ruller_size=0.2;//size of ruler E [0,1] |
horizontal_sbar_data.ruller_pos=0.5;//ruler position E [0,1] |
horizontal_sbar_data.ruller_step=0.1;//step of change ruler pos after press of button E [0,1] |
//create vertical scroll bar |
vertical_sbar_data.x=5; |
vertical_sbar_data.y=26; |
vertical_sbar_data.width=16; |
vertical_sbar_data.height=150; |
vertical_sbar_data.ruller_size=0.5;//size of ruler E [0,1] |
vertical_sbar_data.ruller_pos=0.05;//ruler position E [0,1] |
vertical_sbar_data.ruller_step=0.1;//step of change ruler pos after press of button E [0,1] |
//create horizontal and vertical scroll bars |
ScrollBarH=CreateHorizontalScrollBar(&horizontal_sbar_data); |
ScrollBarV=CreateVerticalScrollBar(&vertical_sbar_data); |
//set callback functions for scroll bars |
id1=SetCallbackFunction(ScrollBarH,SCROLLBAR_CHANGED_EVENT,&ScrollStateH,NULL); |
id2=SetCallbackFunction(ScrollBarV,SCROLLBAR_CHANGED_EVENT,&ScrollStateV,NULL); |
//pack scroll bars in window |
PackControls(window,ScrollBarH); |
PackControls(window,ScrollBarV); |
//start minl libGUI loop |
LibGUImain(window); |
} |
/programs/develop/libraries/libGUI/examples/src/scrolled_window.c |
---|
0,0 → 1,67 |
/* |
test libGUI library |
*/ |
#include "stdarg.h" |
#include "libGUI.h" |
#include "stdio.h" |
#include "stdlib.h" |
#include "string.h" |
void callback_func_delete_window(header_t *control,void *data) |
{ |
QuitLibGUI((parent_t*)control); |
} |
void callback_func(header_t *control,void *data) |
{ |
printf("\npressed button with ID=%d control=%d",(int)control->ctrl_ID,(int)control); |
} |
int main(int argc, char *argv[]) |
{ |
parent_t *window; |
gui_button_data_t button_data; |
gui_button_t *button; |
gui_scrolled_window_data_t scroll_win_data; |
gui_scrolled_window_t *ScrollWin; |
int i,j; |
static char txt[20]; |
//load libGUI library |
LoadLibGUI(NULL); |
//create main window |
window=CreateWindow(); |
//change size of window |
SetWindowSizeRequest(window,270,282); |
//create scrolled window |
scroll_win_data.x=5; |
scroll_win_data.y=5; |
scroll_win_data.width=250; |
scroll_win_data.height=250; |
ScrollWin=CreateScrolledWindow(&scroll_win_data); |
//create buttons |
for(j=1;j<=10;j++) |
{ |
for(i=1;i<=10;i++) |
{ |
button_data.x=10+(i-1)*75; |
button_data.y=10+(j-1)*25; |
button_data.width=70; |
button_data.height=20; |
snprintf(txt,20,"(%d,%d)",j,i); |
button=CreateButtonWithText(&button_data,txt); |
SetCallbackFunction(button,BUTTON_PRESSED_EVENT,&callback_func,NULL); |
ScrolledWindowPackControls(ScrollWin,button); |
} |
} |
//set callback function for button close window |
SetCallbackFunction(window,DELETE_EVENT,&callback_func_delete_window,NULL); |
//pack scrolled window in window |
PackControls(window,ScrollWin); |
//start main libGUI loop |
LibGUImain(window); |
} |
/programs/develop/libraries/libGUI/examples/src/text.c |
---|
0,0 → 1,45 |
/* |
hello world example |
*/ |
#include "libGUI.h" |
#define TRUE 1 |
#define FALSE 0 |
void callback_func_delete_window(header_t *control,void *data) |
{ |
QuitLibGUI((parent_t*)control); |
} |
int main(int argc, char *argv[]) |
{ |
parent_t *window; |
gui_text_data_t txtdata; |
gui_text_t *text; |
//load libGUI library |
LoadLibGUI(NULL);//load from default system path to library |
//create main window |
window=CreateWindow(); |
//change size of window |
SetWindowSizeRequest(window,92,46); |
//set callback function for button close window |
SetCallbackFunction(window,DELETE_EVENT,&callback_func_delete_window,NULL); |
//create control text |
txtdata.x=5; |
txtdata.y=5; |
txtdata.font=NULL;//use default system libGUI font |
txtdata.background=TRUE;//use background for text |
txtdata.color=0xffffff;//text color |
txtdata.background_color=0xff8000;//background color |
txtdata.text="Hello world!"; |
text=CreateText(&txtdata); |
//pack control text in window |
PackControls(window,text); |
//start libGUI main loop |
LibGUImain(window); |
} |
/programs/develop/libraries/libGUI/examples/src |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/libGUI/examples |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/libGUI/. |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |