/*************************************************************************** * Copyright (C) 1994 Charles P. Peterson * * 4007 Enchanted Sun, San Antonio, Texas 78244-1254 * * Email: Charles_P_Peterson@fcircus.sat.tx.us * * * * This is free software with NO WARRANTY. * * See gfft.c, or run program itself, for details. * * Support is available for a fee. * *************************************************************************** * * Program: gfft--General FFT analysis * File: wbtools.c * Purpose: workbench GUI toolkit for GFFT * Author: Charles Peterson (CPP) * History: 19-Nov-1993 CPP; Created. * 4-Aug-94 CPP (1.04); Filenames may contain spaces * 14-Dec-94 CPP (1.16); Fix message indicator for >4 colors * 14-Dec-94 CPP (1.17); Fix button gadgets for >4 colors * 5-Jan-95 CPP (1.18); Use system default font if possible * 17-Jan-95 CPP (1.20); Size shells nicely * 26-Jan-95 CPP (1.26); Allow largest possible font size * 27-Jan-95 CPP (1.27); Report window open failure * 28-Jan-95 CPP (1.29); Labeled radio buttons * 28-Jan-95 CPP (1.30); Tall action buttons * 6-Feb-95 CPP (1.31); Progress requester gadgets * 6-Feb-95 CPP (1.32); Render to window while requester on * 10-Feb-95 CPP (1.34); Thicker requester borders * * Comments: Workbench GUI. Amiga Dependent! * There may be other toolkits. Mine is intended to be * compatible with all releases of AmigaDOS, be fairly * simple, and have a 3d-like look. I've had to make * some small compromises: non-toggle gadgets only * have their borders change when selected (the only good way * to get around this is to have multiple images...with about * an order of magnitude increase in complexity...or by using * BOOPSI, which is fairly complicated itself and 2.0+ * dependent, or use MUI, which would not only necessitate * a complete re-write but also would introduce some copyright * inconsistencies. So, my rationalization anyway is that * there is no _perfect_ choice, and the only better choices * would take much more of my time to implement. I haven't * made enough money on it so far to justify that. */ #ifdef AMIGA #define GUI_DEBUG #include /* sprintf() */ #include /* * Amiga includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* BNDRYOFF */ #include /* GfxBase */ #include #include "gfft.h" #include "wbench.h" #include "settings.h" #define USE_MAX_ROWS_FOR_FONT_CHECK /* * Dialogue Window parameters...pretty good guesses for 2.0 and 1.3 * reset later (some require drawinfo to be available for reset) */ #define SHINE_PEN_20 2 #define SHADOW_PEN_20 1 #define SHINE_PEN_13 1 #define SHADOW_PEN_13 2 #define TEXT_PEN 1 /* Seems to work well under both 2.0 and 1.3 */ #define FILL_TEXT_PEN 2 /* ditto; hmmn, I like better than 2.0 default */ #define FILL_PEN 3 #define BACKGROUND_PEN 0 /* almost guaranteed now, but may be updated */ #define DEFAULT_SCREEN_DEPTH 2 #define DEFAULT_SCREEN_FONT_HEIGHT 8 #define DEFAULT_FONT_HEIGHT 8 #define DEFAULT_FONT_WIDTH 8 #define FONT_COLUMNS_REQUIRED 80 #define FONT_ROWS_REQUIRED 24 #define DEFAULT_SHELL_WIDTH 640 #define DEFAULT_SHELL_HEIGHT 200 #define WINDOW_LEFT 0 /* Same as right edge */ #define WINDOW_TOP 0 /* Allow for WB title & click area above */ #define FIRST_WINDOW_BUTTON_LEFT 12 #define FIRST_WINDOW_BUTTON_TOP 6 #define FIRST_REQUESTER_BUTTON_LEFT 12 #define FIRST_REQUESTER_BUTTON_TOP 6 #define BUTTON_SIDE_EDGE (Font_Width) #define BUTTON_TOP_EDGE 3 /* Inside button to text; same as bottom edge*/ #define BUTTON_TOP_SPACE 2 /* Vertical space between buttons */ /* * Use the following when possible */ #define BUTTON_WIDTH(WIDTH) ((WIDTH) * Font_Width + 2 * BUTTON_SIDE_EDGE) #define BUTTON_HEIGHT (Font_Height + 2 * BUTTON_TOP_EDGE) #define BUTTON_SPACING (BUTTON_HEIGHT + BUTTON_TOP_SPACE) #define BUTTON_TOP(row) (first_button_top + row * BUTTON_SPACING) #define WINDOW_HEIGHT(max_rows) (BUTTON_TOP(max_rows) + \ BUTTON_TOP_SPACE) /* for the bottom edge */ struct TextAttr FontA = { "topaz.font", DEFAULT_FONT_HEIGHT, NULL, NULL }; struct TextAttr *FontAp = &FontA; struct TextFont *fontp = NULL; /* Set if system default font used */ static short shine_pen = SHINE_PEN_20; static short shadow_pen = SHADOW_PEN_20; static short text_pen = TEXT_PEN; static short fill_pen = FILL_PEN; static short fill_text_pen = FILL_TEXT_PEN; static short background_pen = BACKGROUND_PEN; short Screen_Font_Height = DEFAULT_SCREEN_FONT_HEIGHT; short Font_Height = DEFAULT_FONT_HEIGHT; short Font_Width = DEFAULT_FONT_WIDTH; static short screen_depth = DEFAULT_SCREEN_DEPTH; static short first_button_left = FIRST_WINDOW_BUTTON_LEFT; static short first_button_top = FIRST_WINDOW_BUTTON_TOP + DEFAULT_FONT_HEIGHT; static short max_rows = 0; static int gadget_type_mode = NULL; static struct IntuiText *next_textp = NULL; static struct Gadget *next_gadgetp = NULL; static struct Requester *current_requesterp = NULL; #define REQUESTER_STACK_DEPTH 10 static struct Requester *requester_stack[REQUESTER_STACK_DEPTH] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; static int requester_stack_index = 0; struct Library *IntuitionBase = NULL; BOOLEAN Old_Intuition = FALSE; short Max_Columns = 0; int Shell_Width = DEFAULT_SHELL_WIDTH; int Shell_Height = DEFAULT_SHELL_HEIGHT; extern struct Library *AslBase; /* from filereq.c */ extern struct FileRequester *File_Requesterp; static struct Gadget *text_button__new (char *text, short tcol, short trow); void open_libraries (void) { /* * Intuition is currently the only library for which we need to know * version number, hence, we have to open it explicitly. */ if (!IntuitionBase) { IntuitionBase = OpenLibrary ("intuition.library", 37); if (IntuitionBase == NULL) { Old_Intuition = TRUE; IntuitionBase = OpenLibrary ("intuition.library", 0); if (IntuitionBase == NULL) { error_message (CANT_OPEN_INTUITION); gabort (EXIT_FAILURE); } } } } void setup_window_defaults (int max_rows) { struct Screen *screen; struct DrawInfo *draw_info; if (Old_Intuition) { shine_pen = SHINE_PEN_13; /* These usually work for 1.3... */ shadow_pen = SHADOW_PEN_13; /* Should do this better someday */ /* everything else is defaulted */ } else /* Ok, Rev 37 or greater, get pens and fonts */ { if (screen = LockPubScreen (NULL)) { if (draw_info = GetScreenDrawInfo (screen)) { /* vars not used outside this block */ char *system_default_font_name; short system_default_font_height; short system_default_font_width; short screen_width; short screen_height; short save_font_height; shine_pen = draw_info->dri_Pens[SHINEPEN]; shadow_pen = draw_info->dri_Pens[SHADOWPEN]; text_pen = draw_info->dri_Pens[TEXTPEN]; fill_pen = draw_info->dri_Pens[FILLPEN]; fill_text_pen = draw_info->dri_Pens[FILLTEXTPEN]; background_pen = draw_info->dri_Pens[BACKGROUNDPEN]; screen_depth = draw_info->dri_Depth; screen_width = screen->Width; screen_height = screen->Height; Screen_Font_Height = draw_info->dri_Font->tf_YSize; first_button_top = FIRST_WINDOW_BUTTON_TOP + Screen_Font_Height; /* * Get system default font (always monospaced) info... * (Maybe if I make some money on this, I'll rewrite to * use the screen font (which might be proportional). * Test to see that font permits max_rows and * FONT_COLUMNS_REQUIRED * before using (otherwise, we're defaulting to TOPAZ 8). */ system_default_font_name = GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name; system_default_font_height = GfxBase->DefaultFont->tf_YSize; system_default_font_width = GfxBase->DefaultFont->tf_XSize; save_font_height = Font_Height; Font_Height = system_default_font_height; if (!Topaz && #ifndef FORCE_FONT #ifndef USE_MAX_ROWS_FOR_FONT_CHECK (screen_height / system_default_font_height >= FONT_ROWS_REQUIRED) && #else (WINDOW_HEIGHT(max_rows) <= screen_height) && #endif #endif (screen_width / system_default_font_width >= FONT_COLUMNS_REQUIRED)) { FontA.ta_Name = system_default_font_name; FontA.ta_YSize = system_default_font_height; Font_Height = system_default_font_height; Font_Width = system_default_font_width; fontp = GfxBase->DefaultFont; /* Looks nicer without resetting shell height, upped later if needed */ Shell_Width = FONT_COLUMNS_REQUIRED * system_default_font_width; } else { Font_Height = save_font_height; Shell_Height = FONT_ROWS_REQUIRED * system_default_font_height; Shell_Width = FONT_COLUMNS_REQUIRED * system_default_font_width; if (Shell_Height > screen_height) Shell_Height = screen_height; if (Shell_Width > screen_width) Shell_Width = screen_width; } FreeScreenDrawInfo (screen, draw_info); } UnlockPubScreen (NULL, screen); } } } void close_amiga_stuff (void) { if (IntuitionBase) { CloseLibrary (IntuitionBase); IntuitionBase = NULL; } if (File_Requesterp) { FreeAslRequest(File_Requesterp); File_Requesterp = NULL; } if (AslBase) { CloseLibrary(AslBase); AslBase = NULL; } } void gadget__begin (int gadget_type_flag) { gadget_type_mode = gadget_type_flag; Max_Columns = 0; max_rows = 0; next_textp = NULL; next_gadgetp = NULL; if (gadget_type_mode == GTYP_REQGADGET) { first_button_left = FIRST_REQUESTER_BUTTON_LEFT; first_button_top = FIRST_REQUESTER_BUTTON_TOP; } else { first_button_left = FIRST_WINDOW_BUTTON_LEFT; first_button_top = FIRST_WINDOW_BUTTON_TOP + Screen_Font_Height; } } struct Border *requester_border__new (short height, short width, short top_pen, short bottom_pen) { struct Border *rborder; struct Border *nborder; rborder = border__new (height-1, width-1, top_pen, bottom_pen); nborder = rborder->NextBorder->NextBorder = border__new (height-3, width-3, top_pen, bottom_pen); nborder->LeftEdge += 1; nborder->TopEdge += 1; nborder->NextBorder->LeftEdge += 1; nborder->NextBorder->TopEdge += 1; nborder = nborder->NextBorder->NextBorder = border__new (height-5, width-5, top_pen, bottom_pen); nborder->LeftEdge += 2; nborder->TopEdge += 2; nborder->NextBorder->LeftEdge += 2; nborder->NextBorder->TopEdge += 2; return rborder; } struct Border *button_border__new (short width, short top_pen, short bottom_pen) { struct Border *bborder; bborder = border__new (BUTTON_HEIGHT-1, width-1, top_pen, bottom_pen); return bborder; } struct Border *border__new (short height, short width, short top_pen, short bottom_pen) { short *xy_pairs_u, *xy_pairs_l; struct Border *border_u, *border_l; xy_pairs_u = gcalloc (6, sizeof (short), NOTHING_SPECIAL); xy_pairs_l = gcalloc (6, sizeof (short), NOTHING_SPECIAL); border_u = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL); border_l = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL); xy_pairs_u[0] = 0; xy_pairs_u[1] = height; xy_pairs_u[2] = 0; xy_pairs_u[3] = 0; xy_pairs_u[4] = width; xy_pairs_u[5] = 0; xy_pairs_l[0] = 1; /* Looks a little nicer, I think, than 0 */ xy_pairs_l[1] = height; xy_pairs_l[2] = width; xy_pairs_l[3] = height; xy_pairs_l[4] = width; xy_pairs_l[5] = 0; border_u->LeftEdge = 0; border_u->TopEdge = 0; border_u->XY = xy_pairs_u; border_u->FrontPen = top_pen; border_u->DrawMode = JAM1; border_u->NextBorder = border_l; border_u->Count = 3; border_l->LeftEdge = 0; border_l->TopEdge = 0; border_l->XY = xy_pairs_l; border_l->FrontPen = bottom_pen; border_l->DrawMode = JAM1; border_l->NextBorder = NULL; border_l->Count = 3; return border_u; } struct Gadget *progress_gadget__new (short length, short tcol, short trow) { struct Gadget *gadgetp; gadgetp = message_gadget__new (length, tcol, trow); gadgetp->UserData = NULL; return gadgetp; } void progress_gadget__clear (struct Gadget *gadgetp, struct Window *windowp) { gadgetp->UserData = NULL; if (gadgetp->GadgetText) message_gadget__write (gadgetp, NullString, windowp); } void progress_gadget__update (struct Gadget *gadgetp, int percentage, struct Window *windowp) { struct RastPort *rport; UBYTE save_apen; struct Requester *requesterp; int last_percentage = (int) gadgetp->UserData; if (percentage == -1 || last_percentage == -1) { if (last_percentage == -1) return; message_gadget__write (gadgetp, "Unable to measure progress...", windowp); gadgetp->UserData = (APTR) -1; return; } if (last_percentage >= percentage) return; if (percentage > 100 ) percentage = 100; gadgetp->UserData = (APTR) percentage; if (windowp) { short x1, y1, x2, y2; x1 = gadgetp->LeftEdge + 3; y1 = gadgetp->TopEdge + 2; x2 = x1 + (gadgetp->Width - 7) * (percentage/100.0); y2 = y1 + gadgetp->Height - 5; RemoveGadget (windowp, gadgetp); requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; rport = (requesterp) ? requesterp->ReqLayer->rp : windowp->RPort; save_apen = rport->FgPen; SetAPen (rport, (UBYTE) fill_pen); RectFill (rport, x1, y1, x2, y2); SetAPen (rport, (UBYTE) save_apen); AddGList (windowp, gadgetp, -1, 1, requesterp); refresh_gadget (gadgetp, windowp); } } struct Gadget *message_gadget__new (short length, short tcol, short trow) { struct Gadget *mgadgetp; mgadgetp = gadget__new (length, tcol, trow); mgadgetp->Flags = GFLG_GADGHNONE; mgadgetp->Activation = NULL; mgadgetp->GadgetRender = button_border__new (BUTTON_WIDTH (length), shadow_pen, shine_pen); mgadgetp->GadgetText = NULL; return mgadgetp; } struct Gadget *labeled_radio_button__new (char *label, char *text, short tcol, short trow) { short button_offset = strlen (label) + 2; struct Gadget *gadgetp = radio_button__new (text, tcol + button_offset, trow); gadgetp->GadgetText->NextText = button_text__new (label); gadgetp->GadgetText->NextText->LeftEdge -= BUTTON_SIDE_EDGE*2 + strlen (label) * Font_Width; return gadgetp; } struct Gadget *radio_button__new (char *text, short tcol, short trow) { struct Gadget *gadgetp; gadgetp = text_button__new (text, tcol, trow); gadgetp->SelectRender = button_border__new (BUTTON_WIDTH(strlen (text)), shadow_pen, shine_pen); gadgetp->Flags = GFLG_GADGHIMAGE; gadgetp->Activation &= ~GACT_RELVERIFY; gadgetp->Activation &= ~TOGGLESELECT; gadgetp->Activation |= GADGIMMEDIATE; return gadgetp; } struct Gadget *tall_action_button__new (char *text, short tcol, short trow) { struct Gadget *gadgetp; struct Border *borderp; gadgetp = action_button__new (text, tcol, trow); /* * Add extra borders to make button appear taller */ if (screen_depth > 1) { borderp = (struct Border *) gadgetp->GadgetRender; borderp->NextBorder->NextBorder = button_border__new (BUTTON_WIDTH(strlen (text)), shine_pen, shadow_pen); borderp = borderp->NextBorder->NextBorder; borderp->XY[1] += 1; #if FALSE borderp->XY[0] += 1; borderp->XY[2] += 1; borderp->XY[3] += 1; borderp->XY[4] += -1; borderp->XY[5] += 1; #endif borderp = borderp->NextBorder; borderp->XY[0] += 0; borderp->XY[1] += 1; borderp->XY[2] += 1; borderp->XY[3] += 1; borderp->XY[4] += 1; borderp->XY[5] += 1; borderp = (struct Border *) gadgetp->SelectRender; borderp->NextBorder->NextBorder = button_border__new (BUTTON_WIDTH(strlen (text)), shadow_pen, shine_pen); borderp = borderp->NextBorder->NextBorder; borderp->XY[1] += 1; #if FALSE borderp->XY[0] += 1; borderp->XY[2] += 1; borderp->XY[3] += 1; borderp->XY[4] += -1; borderp->XY[5] += 1; #endif borderp = borderp->NextBorder; borderp->XY[0] += 0; borderp->XY[1] += 1; borderp->XY[2] += 1; borderp->XY[3] += 1; borderp->XY[4] += 1; borderp->XY[5] += 1; } return gadgetp; } struct Gadget *action_button__new (char *text, short tcol, short trow) { struct Gadget *gadgetp; gadgetp = text_button__new (text, tcol, trow); if (screen_depth > 1) { gadgetp->SelectRender = button_border__new (BUTTON_WIDTH(strlen (text)), shadow_pen, shine_pen); gadgetp->Flags = GFLG_GADGHIMAGE; } return gadgetp; } static struct Gadget *text_button__new (char *text, short tcol, short trow) { struct Gadget *gadgetp; gadgetp = gadget__new (strlen (text), tcol, trow); gadgetp->GadgetText = button_text__new (text); return gadgetp; } struct Gadget *gadget__new (short length, short tcol, short trow) { struct Gadget *gadgetp; short local_max_column = length + tcol; if (local_max_column > Max_Columns) Max_Columns = local_max_column; if (trow + 1 > max_rows) max_rows = trow + 1; gadgetp = gcalloc (1, sizeof (struct Gadget), NOTHING_SPECIAL); gadgetp->NextGadget = next_gadgetp; next_gadgetp = gadgetp; gadgetp->LeftEdge = first_button_left + tcol * Font_Width; gadgetp->TopEdge = first_button_top + trow * BUTTON_SPACING; gadgetp->Width = BUTTON_WIDTH (length); gadgetp->Height = BUTTON_HEIGHT; gadgetp->Activation = GACT_RELVERIFY; gadgetp->GadgetType = GTYP_BOOLGADGET | gadget_type_mode; gadgetp->GadgetRender = button_border__new (BUTTON_WIDTH (length), shine_pen, shadow_pen); gadgetp->SelectRender = NULL; gadgetp->Flags = GFLG_GADGHCOMP; gadgetp->GadgetText = NULL; gadgetp->MutualExclude = NULL; gadgetp->SpecialInfo = NULL; gadgetp->GadgetID = NULL; gadgetp->UserData = NULL; return gadgetp; } struct StringInfo *string_info__new (short max_chars, short vis_chars) { struct StringInfo *string_info; string_info = gcalloc (1, sizeof (struct StringInfo), NOTHING_SPECIAL); string_info->Buffer = gcalloc (1, max_chars+1, NOTHING_SPECIAL); string_info->MaxChars = max_chars+1; string_info->UndoBuffer = NULL; string_info->BufferPos = 0; string_info->DispPos = 0; string_info->CTop = BUTTON_TOP_EDGE; string_info->CLeft = BUTTON_SIDE_EDGE; string_info->DispCount = vis_chars; if (fontp) { struct StringExtend *string_extendp = gcalloc (1, sizeof (struct StringExtend), NOTHING_SPECIAL); string_extendp->Font = fontp; string_extendp->Pens[0] = text_pen; string_extendp->Pens[1] = background_pen; string_extendp->ActivePens[0] = text_pen; string_extendp->ActivePens[1] = background_pen; string_info->Extension = string_extendp; } return string_info; } struct Gadget *string_gadget__new (char *prompt, char *initial_name, short max_chars, short length, short tcol, short trow) { struct Gadget *string_gadgetp; struct Border *borderp; struct Border *bottomp; short *bottom_xy; short right_text_offset, right_border_offset; short container_length, container_tcol; /* * (Damn! Intuition doesn't allow user offset for string gadget container * offsets within overall gadget area, so must do it manually.) */ container_length = length - (strlen (prompt) + 2); container_tcol = tcol + (strlen (prompt) + 2); string_gadgetp = gadget__new (container_length, container_tcol, trow); string_gadgetp->GadgetType = GTYP_STRGADGET | gadget_type_mode; string_gadgetp->Activation |= GADGIMMEDIATE; if (fontp) string_gadgetp->Flags |= GFLG_STRINGEXTEND; string_gadgetp->SpecialInfo = string_info__new (max_chars, length-4); string_gadgetp->GadgetText = button_text__new (prompt); right_border_offset = BUTTON_SIDE_EDGE; right_text_offset = BUTTON_SIDE_EDGE*2 + strlen (prompt) * Font_Width + right_border_offset; string_gadgetp->GadgetText->LeftEdge -= right_text_offset; string_gadgetp->LeftEdge += right_border_offset; borderp = (struct Border *) string_gadgetp->GadgetRender; borderp->XY[0] -= right_border_offset; borderp->XY[2] -= right_border_offset; borderp->XY[4] -= right_border_offset; borderp = borderp->NextBorder; borderp->XY[0] -= right_border_offset; borderp->XY[2] -= right_border_offset; borderp->XY[4] -= right_border_offset; string_gadgetp->Width -= right_border_offset + BUTTON_SIDE_EDGE; string_gadgetp->TopEdge += BUTTON_TOP_EDGE; string_gadgetp->GadgetText->TopEdge -= BUTTON_TOP_EDGE; borderp = (struct Border *) string_gadgetp->GadgetRender; borderp->XY[1] -= BUTTON_TOP_EDGE; borderp->XY[3] -= BUTTON_TOP_EDGE; borderp->XY[5] -= BUTTON_TOP_EDGE; borderp = borderp->NextBorder; borderp->XY[1] -= BUTTON_TOP_EDGE; borderp->XY[3] -= BUTTON_TOP_EDGE; borderp->XY[5] -= BUTTON_TOP_EDGE; string_gadgetp->Height -= BUTTON_TOP_EDGE * 2; /* * Add "bottom line" */ bottomp = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL); bottom_xy = gcalloc (4, sizeof (short), NOTHING_SPECIAL); bottom_xy[0] = 0; bottom_xy[1] = Font_Height; bottom_xy[2] = container_length * Font_Width; bottom_xy[3] = Font_Height; bottomp->LeftEdge = 0; bottomp->TopEdge = 0; bottomp->XY = bottom_xy; bottomp->FrontPen = shadow_pen; bottomp->DrawMode = JAM1; bottomp->NextBorder = NULL; bottomp->Count = 2; borderp->NextBorder = bottomp; if (initial_name) { struct StringInfo *string_info = string_gadgetp->SpecialInfo; strcpy (string_info->Buffer, initial_name); } return string_gadgetp; } struct IntuiText *requester_text__new (char *text, short tcol, short trow) { struct IntuiText *textst; short local_max_column = tcol + strlen (text); if (local_max_column > Max_Columns) Max_Columns = local_max_column; if (trow + 1 > max_rows) max_rows = trow + 1; textst = button_text__new (text); textst->LeftEdge = first_button_left + BUTTON_SIDE_EDGE + tcol * Font_Width; textst->TopEdge = BUTTON_TOP_EDGE + BUTTON_TOP(trow); textst->NextText = next_textp; next_textp = textst; return textst; } struct IntuiText *button_text__new (char *text) { struct IntuiText *textst; textst = gcalloc (1, sizeof (struct IntuiText), NOTHING_SPECIAL); textst->FrontPen = text_pen; textst->BackPen = background_pen; textst->DrawMode = JAM1; textst->LeftEdge = BUTTON_SIDE_EDGE; textst->TopEdge = BUTTON_TOP_EDGE; textst->ITextFont = FontAp; /* textst->ITextFont = NULL; This gives screen font, may be prop font */ textst->IText = text; textst->NextText = NULL; return textst; } void refresh_gadget (struct Gadget *gadgetp, struct Window *windowp) { struct Requester *requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; RefreshGList (gadgetp, windowp, requesterp, 1); } void toggle_button__toggle (struct Gadget *gadgetp, char *(*on_function)(char *arg), char *(*off_function)(char *arg), struct Window *windowp) { if (!(gadgetp->Flags & GFLG_SELECTED)) { (*off_function) (NullString); } else { (*on_function) (NullString); } } void radio_button__toggle (struct Gadget *gadgetp, char *(*on_function)(char *arg), char *(*off_function)(char *arg), struct Window *windowp) { /* * Must do imagery here for radio buttons */ if (gadgetp->Flags & GFLG_SELECTED) { (*off_function) (NullString); radio_button__out (gadgetp, windowp); } else { (*on_function) (NullString); radio_button__in (gadgetp, windowp); } } char *string_gadget__apply (struct Gadget *string_gadgetp, char *(*apply_function)(char *arg)) { struct StringInfo *string_infop = string_gadgetp->SpecialInfo; char *buffer = string_infop->Buffer; buffer[string_infop->NumChars] = '\0'; (*apply_function) (buffer); return buffer; } /* * (1.04) Names in requesters may include spaces, so * must be quoted */ char *name_string_gadget__apply (struct Gadget *string_gadgetp, char *(*apply_function)(char *arg)) { char *enquote_buffer; struct StringInfo *string_infop = string_gadgetp->SpecialInfo; char *buffer = string_infop->Buffer; buffer[string_infop->NumChars] = '\0'; if (!string_infop->NumChars) { (*apply_function) (buffer); /* Null String; don't enquote */ } else { enquote_buffer = gmalloc (string_infop->NumChars + 8, NOTHING_SPECIAL); sprintf (enquote_buffer, "\"%s\"", buffer); (*apply_function) (enquote_buffer); gfree (enquote_buffer); } return buffer; } void string_gadget__reset (struct Gadget *string_gadgetp, char *new_string, struct Window *windowp) { struct StringInfo *string_infop = string_gadgetp->SpecialInfo; char *buffer = string_infop->Buffer; int string_length = 0; if (!new_string || (string_length = strlen (new_string)) <= 0) { buffer[0] = '\0'; } else { strcpy (buffer, new_string); } string_infop->NumChars = string_length; refresh_gadget (string_gadgetp, windowp); } void message_requester (struct Window *windowp, char *message_text) { extern char *Got_It_S; struct IntuiText *mtextp = button_text__new (message_text); struct IntuiText *got_it_textp = button_text__new (Got_It_S); if (Old_Intuition) { mtextp->DrawMode = JAM2 | INVERSVID; got_it_textp->DrawMode = JAM2 | INVERSVID; } AutoRequest (windowp, mtextp, NULL, got_it_textp, IDCMP_GADGETDOWN, IDCMP_GADGETDOWN, 640, 50); gfree (mtextp); gfree (got_it_textp); } /* * I have decided NOT to follow the guidelines for 'mutually exclusive' * gadgets on page 140 of the Amiga Rom Kernel Reference Manual, Third * Edition, which specifically advise against this combination (mutually * exclusive gadgets using 'complementing'--though I don't really use * 'complementing' here anymore--I use explicit colors to be compatible with * larger numbers of colors). * * However, I have chosen instead to follow the guidelines for 'Updating * a Gadget's Imagery' on pages 129-130. Before a radio_button is * refreshed in either selected or unselected state, the background * behind it is restored ("cleared") with RectFill. I do this very * carefully as you will see. * * This concept has been extended to cover other features, such as * gadget disable and enable, which I couldn't get to work before. * * This should be acceptable and stable with future released of Intuition. * At least, there is some hope. And it works with 1.2-2.1 for sure. * * It now even handles requester gadgets properly. */ void radio_button__in (struct Gadget *gadgetp, struct Window *windowp) { struct RastPort *rport; short x1, y1, x2, y2; UBYTE save_apen; /* I preserve this one, dunno if necessary */ struct Requester *requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; if (windowp) { /* if (!(gadgetp->Flags & GFLG_SELECTED)) /* pushing my luck too far*/ { RemoveGadget (windowp, gadgetp); gadgetp->Flags |= GFLG_SELECTED; gadgetp->GadgetText->FrontPen = fill_text_pen; gadgetp->GadgetText->BackPen = fill_pen; rport = (requesterp) ? requesterp->ReqLayer->rp : windowp->RPort; save_apen = rport->FgPen; SetAPen (rport, (UBYTE) fill_pen); SetDrMd (rport, JAM1); SetAfPt (rport, NULL, 0); SetWrMsk (rport, (UBYTE) 0xff); BNDRYOFF (rport); x1 = gadgetp->LeftEdge; y1 = gadgetp->TopEdge; x2 = x1 + gadgetp->Width - 1; y2 = y1 + gadgetp->Height - 1; RectFill (rport, x1, y1, x2, y2); SetAPen (rport, (UBYTE) save_apen); AddGList (windowp, gadgetp, -1, 1, requesterp); refresh_gadget (gadgetp, windowp); } } else /* if (!windowp) */ { gadgetp->Flags |= GFLG_SELECTED; } } void radio_button__out (struct Gadget *gadgetp, struct Window *windowp) { struct RastPort *rport; short x1, y1, x2, y2; UBYTE save_apen; /* I preserve this one, dunno if necessary */ struct Requester *requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; if (windowp) { if (gadgetp->Flags & GFLG_SELECTED) { RemoveGadget (windowp, gadgetp); gadgetp->Flags &= ~GFLG_SELECTED; gadgetp->GadgetText->FrontPen = text_pen; gadgetp->GadgetText->BackPen = background_pen; rport = (requesterp) ? requesterp->ReqLayer->rp : windowp->RPort; save_apen = rport->FgPen; SetAPen (rport, (UBYTE) background_pen); SetDrMd (rport, JAM1); SetAfPt (rport, NULL, 0); SetWrMsk (rport, (UBYTE) 0xff); BNDRYOFF (rport); x1 = gadgetp->LeftEdge; y1 = gadgetp->TopEdge; x2 = x1 + gadgetp->Width - 1; y2 = y1 + gadgetp->Height - 1; RectFill (rport, x1, y1, x2, y2); SetAPen (rport, (UBYTE) save_apen); AddGList (windowp, gadgetp, -1, 1, requesterp); refresh_gadget (gadgetp, windowp); } } else /* if (!windowp) */ { gadgetp->Flags &= ~GFLG_SELECTED; } } void gadget__disable (struct Gadget *gadgetp, struct Window *windowp) { struct RastPort *rport; short x1, y1, x2, y2; UBYTE save_apen; /* I preserve this one, dunno if necessary */ struct Requester *requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; if (gadgetp->Flags & GFLG_DISABLED) return; if (!windowp) { gadgetp->Flags |= GFLG_DISABLED; return; } RemoveGadget (windowp, gadgetp); gadgetp->Flags |= GFLG_DISABLED; rport = (requesterp) ? requesterp->ReqLayer->rp : windowp->RPort; save_apen = rport->FgPen; if (gadgetp->Flags & GFLG_SELECTED) { SetAPen (rport, (UBYTE) fill_pen); } else { SetAPen (rport, (UBYTE) background_pen); } SetDrMd (rport, JAM1); SetAfPt (rport, NULL, 0); SetWrMsk (rport, (UBYTE) 0xff); BNDRYOFF (rport); x1 = gadgetp->LeftEdge; y1 = gadgetp->TopEdge; x2 = x1 + gadgetp->Width - 1; y2 = y1 + gadgetp->Height - 1; RectFill (rport, x1, y1, x2, y2); SetAPen (rport, (UBYTE) save_apen); AddGList (windowp, gadgetp, -1, 1, requesterp); refresh_gadget (gadgetp, windowp); } void gadget__enable (struct Gadget *gadgetp, struct Window *windowp) { struct RastPort *rport; short x1, y1, x2, y2; UBYTE save_apen; /* I preserve this one, dunno if necessary */ struct Requester *requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; if (!(gadgetp->Flags & GFLG_DISABLED)) return; if (!windowp) { gadgetp->Flags |= GFLG_DISABLED; return; } /* Yes, of course, OnGadget isn't smart enough for border gadgets */ RemoveGadget (windowp, gadgetp); gadgetp->Flags &= ~GFLG_DISABLED; rport = (requesterp) ? requesterp->ReqLayer->rp : windowp->RPort; save_apen = rport->FgPen; if (gadgetp->Flags & GFLG_SELECTED) { SetAPen (rport, (UBYTE) fill_pen); } else { SetAPen (rport, (UBYTE) background_pen); } SetDrMd (rport, JAM1); SetAfPt (rport, NULL, 0); SetWrMsk (rport, (UBYTE) 0xff); BNDRYOFF (rport); x1 = gadgetp->LeftEdge; y1 = gadgetp->TopEdge; x2 = x1 + gadgetp->Width - 1; y2 = y1 + gadgetp->Height - 1; RectFill (rport, x1, y1, x2, y2); SetAPen (rport, (UBYTE) save_apen); AddGList (windowp, gadgetp, -1, 1, requesterp); refresh_gadget (gadgetp, windowp); } void message_gadget__write (struct Gadget *gadgetp, char *message, struct Window *windowp) { struct RastPort *rport; UBYTE save_apen; /* I preserve this one, dunno if necessary */ struct Requester *requesterp = (gadgetp->GadgetType & GTYP_REQGADGET) ? current_requesterp : NULL; if (windowp) RemoveGadget (windowp, gadgetp); if (gadgetp->GadgetText) gfree (gadgetp->GadgetText); if (!message || !strlen(message)) { gadgetp->GadgetText = NULL; } else { gadgetp->GadgetText = button_text__new (message); } /* gadgetp->GadgetText->FrontPen = fill_text_pen; */ if (windowp) { short x1, y1, x2, y2; x1 = gadgetp->LeftEdge; y1 = gadgetp->TopEdge; x2 = x1 + gadgetp->Width - 1; y2 = y1 + gadgetp->Height - 1; rport = (requesterp) ? requesterp->ReqLayer->rp : windowp->RPort; save_apen = rport->FgPen; SetAPen (rport, (UBYTE) background_pen); RectFill (rport, x1, y1, x2, y2); SetAPen (rport, (UBYTE) save_apen); AddGList (windowp, gadgetp, -1, 1, requesterp); refresh_gadget (gadgetp, windowp); } } struct Window *window__new (char *title) { struct NewWindow new_window; /* parameter structure to create window */ struct Window *windowp = NULL; short height = WINDOW_HEIGHT (max_rows); short width = (Max_Columns * Font_Width) + (2 * (FIRST_WINDOW_BUTTON_LEFT + BUTTON_SIDE_EDGE)); if (Shell_Height < height) Shell_Height = height; if (Shell_Width < width) Shell_Width = width; new_window.LeftEdge = WINDOW_LEFT; new_window.TopEdge = WINDOW_TOP; new_window.Height = height; new_window.Width = width; new_window.DetailPen = 0; new_window.BlockPen = 1; new_window.Title = title; new_window.Flags = SMART_REFRESH | ACTIVATE | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH; new_window.IDCMPFlags = IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_RAWKEY; if (Old_Intuition) { new_window.Type = WBENCHSCREEN; } else { new_window.Type = PUBLICSCREEN; /* It's the latest thing */ } new_window.FirstGadget = next_gadgetp; new_window.Screen = NULL; new_window.BitMap = NULL; new_window.MinWidth = 0; new_window.MinHeight = 0; new_window.MaxWidth = 0; new_window.MaxHeight = 0; /* Try to open the window. Like the call to OpenLibrary(), if * the OpenWindow call is successful, it returns a pointer to * the structure for your new window. If the OpenWindow() call * fails, it returns a zero. */ if ((windowp = (struct Window *) OpenWindow (&new_window)) == NULL ) { error_message (WINDOW_OPEN_FAILED); gabort (EXIT_FAILURE); } return windowp; } struct Requester *requester__new (void) { struct Requester *requesterp; short height = (max_rows * (Font_Height + (2 * BUTTON_TOP_EDGE))) + ((max_rows - 1) * BUTTON_TOP_SPACE) + + (2 * FIRST_REQUESTER_BUTTON_TOP); short width = (Max_Columns * Font_Width) + (2 * (FIRST_REQUESTER_BUTTON_LEFT + BUTTON_SIDE_EDGE)); requesterp = gmalloc (sizeof (struct Requester), NOTHING_SPECIAL); InitRequester (requesterp); requesterp->BackFill = background_pen; requesterp->ReqBorder = requester_border__new (height, width, shine_pen, shadow_pen); requesterp->Width = width; requesterp->Height = height; requesterp->RelLeft = 0; requesterp->RelTop = 0; requesterp->Flags = POINTREL; return requesterp; } BOOLEAN requester__display (struct Requester *rp, struct Window *wp) { if (Request (rp, wp)) { if (++requester_stack_index >= REQUESTER_STACK_DEPTH) { error_message (REQUESTER_STACK_OVERFLOW); EndRequest (rp, wp); return FALSE; } requester_stack[requester_stack_index] = current_requesterp; current_requesterp = rp; return TRUE; } return FALSE; } void requester__remove (struct Requester *rp, struct Window *wp) { current_requesterp = requester_stack[requester_stack_index]; if (requester_stack_index) requester_stack_index--; EndRequest (rp, wp); } BOOLEAN ignore_tooltype (char *tooltype) { if (!strncmp (tooltype, "TOOLPRI", 7)) return TRUE; if (!strncmp (tooltype, "STARTPRI", 8)) return TRUE; if (!strncmp (tooltype, "DONOTWAIT", 9)) return TRUE; if (!strncmp (tooltype, "FILETYPE", 8)) return TRUE; if (!strncmp (tooltype, "DUMMY", 5)) return TRUE; return FALSE; } #endif /* ifdef AMIGA */