// Edit a filetype action void filetypeed_edit_action( filetype_ed_data *data, short action, char *name) { Cfg_Function *function; FunctionStartup *startup; BOOL success=0; // Allocate startup data if (!(startup=AllocVec(sizeof(FunctionStartup),MEMF_CLEAR))) return; // Find the function we want to edit if (!(function=FindFunctionType(&data->type->function_list,action))) { // Allocate a new function function=NewFunction(0,action); } // Otherwise, copy the function else function=CopyFunction(function,0,0); // Valid function? if (function) { // Copy startup data *startup=data->func_startup; startup->window=data->window; startup->function=function; startup->owner_ipc=data->ipc; startup->object=data->type; startup->object_flags=action; // Build title lsprintf(startup->title,"%s : %s",data->type->type.name,name); // Launch editor if ((IPC_Launch( &data->proc_list, &data->editor[action], "dopus_function_editor", (ULONG)IPC_NATIVE(FunctionEditor), STACK_DEFAULT, (ULONG)startup, (struct Library *)DOSBase)) && data->editor[action]) success=1; } // Free data if not successful if (!success) { FreeFunction(function); FreeVec(startup); } }
void NewFunc (SymEntry* Func) /* Parse argument declarations and function body. */ { int C99MainFunc = 0;/* Flag for C99 main function returning int */ SymEntry* Param; /* Get the function descriptor from the function entry */ FuncDesc* D = Func->V.F.Func; /* Allocate the function activation record for the function */ CurrentFunc = NewFunction (Func); /* Reenter the lexical level */ ReenterFunctionLevel (D); /* Check if the function header contains unnamed parameters. These are * only allowed in cc65 mode. */ if ((D->Flags & FD_UNNAMED_PARAMS) != 0 && (IS_Get (&Standard) != STD_CC65)) { Error ("Parameter name omitted"); } /* Declare two special functions symbols: __fixargs__ and __argsize__. * The latter is different depending on the type of the function (variadic * or not). */ AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize); if (D->Flags & FD_VARIADIC) { /* Variadic function. The variable must be const. */ static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) }; AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0); } else { /* Non variadic */ AddConstSym ("__argsize__", type_uchar, SC_DEF | SC_CONST, D->ParamSize); } /* Function body now defined */ Func->Flags |= SC_DEF; /* Special handling for main() */ if (strcmp (Func->Name, "main") == 0) { /* Mark this as the main function */ CurrentFunc->Flags |= FF_IS_MAIN; /* Main cannot be a fastcall function */ if (IsQualFastcall (Func->Type)) { Error ("`main' cannot be declared as __fastcall__"); } /* If cc65 extensions aren't enabled, don't allow a main function that * doesn't return an int. */ if (IS_Get (&Standard) != STD_CC65 && CurrentFunc->ReturnType[0].C != T_INT) { Error ("`main' must always return an int"); } /* Add a forced import of a symbol that is contained in the startup * code. This will force the startup code to be linked in. */ g_importstartup (); /* If main() takes parameters, generate a forced import to a function * that will setup these parameters. This way, programs that do not * need the additional code will not get it. */ if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) { g_importmainargs (); } /* Determine if this is a main function in a C99 environment that * returns an int. */ if (IsTypeInt (F_GetReturnType (CurrentFunc)) && IS_Get (&Standard) == STD_C99) { C99MainFunc = 1; } } /* Allocate code and data segments for this function */ Func->V.F.Seg = PushSegments (Func); /* Allocate a new literal pool */ PushLiteralPool (Func); /* If this is a fastcall function, push the last parameter onto the stack */ if (IsQualFastcall (Func->Type) && D->ParamCount > 0) { unsigned Flags; /* Fastcall functions may never have an ellipsis or the compiler is buggy */ CHECK ((D->Flags & FD_VARIADIC) == 0); /* Generate the push */ if (IsTypeFunc (D->LastParam->Type)) { /* Pointer to function */ Flags = CF_PTR; } else { Flags = TypeOf (D->LastParam->Type) | CF_FORCECHAR; } g_push (Flags, 0); } /* Generate function entry code if needed */ g_enter (TypeOf (Func->Type), F_GetParamSize (CurrentFunc)); /* If stack checking code is requested, emit a call to the helper routine */ if (IS_Get (&CheckStack)) { g_stackcheck (); } /* Setup the stack */ StackPtr = 0; /* Walk through the parameter list and allocate register variable space * for parameters declared as register. Generate code to swap the contents * of the register bank with the save area on the stack. */ Param = D->SymTab->SymHead; while (Param && (Param->Flags & SC_PARAM) != 0) { /* Check for a register variable */ if (SymIsRegVar (Param)) { /* Allocate space */ int Reg = F_AllocRegVar (CurrentFunc, Param->Type); /* Could we allocate a register? */ if (Reg < 0) { /* No register available: Convert parameter to auto */ CvtRegVarToAuto (Param); } else { /* Remember the register offset */ Param->V.R.RegOffs = Reg; /* Generate swap code */ g_swap_regvars (Param->V.R.SaveOffs, Reg, CheckedSizeOf (Param->Type)); } } /* Next parameter */ Param = Param->NextSym; } /* Need a starting curly brace */ ConsumeLCurly (); /* Parse local variable declarations if any */ DeclareLocals (); /* Remember the current stack pointer. All variables allocated elsewhere * must be dropped when doing a return from an inner block. */ CurrentFunc->TopLevelSP = StackPtr; /* Now process statements in this block */ while (CurTok.Tok != TOK_RCURLY && CurTok.Tok != TOK_CEOF) { Statement (0); } /* If this is not a void function, and not the main function in a C99 * environment returning int, output a warning if we didn't see a return * statement. */ if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc) { Warning ("Control reaches end of non-void function"); } /* If this is the main function in a C99 environment returning an int, let * it always return zero. Note: Actual return statements jump to the return * label defined below. * The code is removed by the optimizer if unused. */ if (C99MainFunc) { g_getimmed (CF_INT | CF_CONST, 0, 0); } /* Output the function exit code label */ g_defcodelabel (F_GetRetLab (CurrentFunc)); /* Restore the register variables */ F_RestoreRegVars (CurrentFunc); /* Generate the exit code */ g_leave (); /* Emit references to imports/exports */ EmitExternals (); /* Emit function debug info */ F_EmitDebugInfo (); EmitDebugInfo (); /* Leave the lexical level */ LeaveFunctionLevel (); /* Eat the closing brace */ ConsumeRCurly (); /* Restore the old literal pool, remembering the one for the function */ Func->V.F.LitPool = PopLiteralPool (); /* Switch back to the old segments */ PopSegments (); /* Reset the current function pointer */ FreeFunction (CurrentFunc); CurrentFunc = 0; }
void FunctionEditor(void) { struct IntuiMessage *gmsg,msg; int break_flag=0; UWORD gadgetid=0; ULONG waitbits; FuncEdData *data; IPCData *ipc; NewConfigWindow newwin; FunctionStartup *startup=0; IPCMessage *submsg; int success=0; BOOL open_window=1; BPTR lock; ConfigWindow windims; // Do startup if (!(ipc=Local_IPC_ProcStartup((ULONG *)&startup, (APTR)&funced_init))) { funced_cleanup(startup->data); return; } // Get data pointer data=startup->data; // Lock RAM: and CD to it if ((lock=Lock("ram:",ACCESS_READ))) lock=CurrentDir(lock); // Copy dimensions if (startup->flags&FUNCEDF_CENTER) windims=_function_editor_window_center; else if (startup->flags&FUNCEDF_LABEL) windims=_function_editor_label_window; else windims=_function_editor_window; // Fill in new window newwin.parent=startup->window; newwin.dims=&windims; newwin.title=(startup->title[0])?startup->title:(char *)GetString(startup->locale,MSG_FUNCED_TITLE); newwin.locale=startup->locale; newwin.port=0; newwin.flags=WINDOW_VISITOR|WINDOW_AUTO_KEYS|WINDOW_REQ_FILL;//|WINDOW_SIZE_BOTTOM; newwin.font=0; // Build flag list funced_build_flaglist(data); waitbits=1<<ipc->command_port->mp_SigBit|1<<data->drag.timer->port->mp_SigBit; // Event loop FOREVER { // Check drag if (config_drag_check(&data->drag)) { // End drag functioned_end_drag(data,0); } // Task message? while ((submsg=(IPCMessage *)GetMsg(ipc->command_port))) { // Close message? if (submsg->command==IPC_QUIT) { // Keep changes? success=submsg->flags; // Set break flag break_flag=1; } // Activate else if (submsg->command==IPC_ACTIVATE && data->window) { WindowToFront(data->window); ActivateWindow(data->window); } // Hide else if (submsg->command==IPC_HIDE && data->window) { // Store changes in function funced_store_edits(data); // End any drag in progress functioned_end_drag(data,0); // Remove AppWindow RemoveAppWindow(data->appwindow); data->appwindow=0; // Close window CloseConfigWindow(data->window); // Zero stuff data->window=0; data->objlist=0; waitbits=1<<ipc->command_port->mp_SigBit; } // Show else if (submsg->command==IPC_SHOW && !data->window) { // Set flag to open window open_window=1; newwin.parent=(struct Window *)submsg->data; } // Passed-along app message else if (submsg->command==CFG_APPMESSAGE_PASS) { funced_appmsg(data,submsg->data); ReplyMsg((struct Message *)submsg->data); } // Update our identity else if (submsg->command==CFG_NEW_ID) { data->function->function.func_type=submsg->flags; startup->object_flags=(ULONG)submsg->data; } // Copy a function else if (submsg->command==FUNCTIONEDIT_COPY_LINE) { FunctionEntry *entry,*next; // Copy function functioned_copy_line( data, (FunctionEntry *)submsg->data, 0, (Point *)submsg->data_free); // Free function entry=(FunctionEntry *)submsg->data; while (entry) { // Get next next=(FunctionEntry *)entry->node; // Free entry FreeVec(entry); entry=next; } } // Clip button else if (submsg->command==BUTTONEDIT_CLIP_BUTTON) { Cfg_ButtonFunction *func; // Show busy pointer SetWindowBusy(data->window); // Stop editing funced_end_edit(data,data->edit_node,0,0); data->edit_node=0; // Get first function if ((func=(Cfg_ButtonFunction *) FindFunctionType( (struct List *)&((Cfg_Button *)submsg->data)->function_list, FTYPE_LEFT_BUTTON))) { FunctionEntry dummy; Cfg_Instruction *ins; // Go through instructions for (ins=(Cfg_Instruction *)func->instructions.mlh_Head; ins->node.mln_Succ; ins=(Cfg_Instruction *)ins->node.mln_Succ) { // Fill out dummy entry dummy.type=ins->type; if (ins->string) strcpy(dummy.buffer,ins->string); else dummy.buffer[0]=0; // Copy function line data->edit_node=funced_new_entry(data,0,&dummy); } // Start editing last line funced_start_edit(data); // Get flags data->function->function.flags=func->function.flags; data->function->function.code=func->function.code; data->function->function.qual=func->function.qual; data->function->function.qual_mask=func->function.qual_mask; data->function->function.qual_same=func->function.qual_same; // Update flag list funced_update_flaglist(data); // Update key funced_show_key(data); } // Free button FreeButton((Cfg_Button *)submsg->data); // Clear busy pointer ClearWindowBusy(data->window); } // Reply the message IPC_Reply(submsg); } // Open window? if (open_window) { // Open window if (!(data->window=OpenConfigWindow(&newwin)) || !(data->p_objlist=AddObjectList( data->window, (startup->flags&FUNCEDF_IMAGE)?_function_editor_image_objects: ((startup->flags&FUNCEDF_LABEL)?_function_editor_label_objects: _function_editor_normal_objects))) || !(data->objlist=AddObjectList(data->window,_function_editor_objects))) break; // Add use or save button AddObjectList(data->window,(startup->flags&FUNCEDF_SAVE)?_function_editor_objects_save:_function_editor_objects_use); // Store window for drag data->drag.window=data->window; // Set window ID SetWindowID(data->window,0,WINDOW_FUNCTION_EDITOR,(struct MsgPort *)ipc); // Add menus AddWindowMenus(data->window,_funced_menus); // Make this an AppWindow data->appwindow=AddAppWindowA(0,0,data->window,data->appport,0); // Get waitbits waitbits|=1<<data->window->UserPort->mp_SigBit; if (data->appwindow) waitbits|=1<<data->appport->mp_SigBit; // Disable key? if (startup->flags&FUNCEDF_NO_KEY) { DisableObject(data->objlist,GAD_FUNCED_KEY,TRUE); } // Initialise gadgets with function data. funced_init_gads(data); open_window=0; } // Intuimessage if (data->window) { while ((gmsg=GetWindowMsg(data->window->UserPort))) { Att_Node *node; // Copy message and reply (unless IDCMPUPDATE) msg=*gmsg; if (gmsg->Class!=IDCMP_IDCMPUPDATE) { ReplyWindowMsg(gmsg); gmsg=0; } // Get GadgetID if (msg.Class==IDCMP_GADGETDOWN || msg.Class==IDCMP_GADGETUP) gadgetid=((struct Gadget *)msg.IAddress)->GadgetID; // Look at message switch (msg.Class) { // Key press case IDCMP_VANILLAKEY: // If editing something, activate string gadget if (data->edit_node) ActivateStrGad(GADGET(GetObject(data->objlist,GAD_FUNCED_EDIT)),data->window); break; // Close window case IDCMP_CLOSEWINDOW: // Set break flag break_flag=1; break; // Mouse move case IDCMP_MOUSEMOVE: // Handle drag move config_drag_move(&data->drag); break; // Inactive window does menu down case IDCMP_INACTIVEWINDOW: msg.Code=MENUDOWN; // Mouse buttons case IDCMP_MOUSEBUTTONS: // Valid drag info? if (data->drag.drag) { short ok=-1; // Dropped ok? if (msg.Code==SELECTUP) { // Is shift down? if (msg.Qualifier&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) data->drag_shift=1; else data->drag_shift=0; // Remember last position data->drag.drag_x=data->window->WScreen->MouseX; data->drag.drag_y=data->window->WScreen->MouseY; ok=1; } // Aborted else if (msg.Code==MENUDOWN) { // Set abort ok=0; } // End drag? if (ok!=-1) functioned_end_drag(data,ok); } break; // Menu case IDCMP_MENUPICK: { struct MenuItem *item; // Get item if (!(item=ItemAddress(data->window->MenuStrip,msg.Code))) break; // Treat as gadget gadgetid=MENUID(item); } // Gadget case IDCMP_GADGETUP: case IDCMP_GADGETDOWN: // Look at gadget ID switch (gadgetid) { // Hotkey case GAD_FUNCED_KEY: { IX ix; char *ptr; // Get key, see if it's invalid if ((ptr=(char *)GetGadgetValue(data->objlist,GAD_FUNCED_KEY)) && *ptr) { // Try to parse if (ParseIX(ptr,&ix)) { // Flash screen DisplayBeep(data->window->WScreen); // Activate key field again ActivateStrGad(GADGET(GetObject(data->objlist,GAD_FUNCED_KEY)),data->window); } else { data->function->function.code=ix.ix_Code; data->function->function.qual=QualValid(ix.ix_Qualifier); data->function->function.qual_mask=ix.ix_QualMask; data->function->function.qual_same=ix.ix_QualSame; } } } break; // Flag selected case GAD_FUNCED_FLAGS: // Get selected node node=Att_FindNode(data->flag_list,msg.Code); // Set flag data->function->function.flags^=node->data; // Check change funced_check_flag(&data->function->function.flags,node->data); // Update flag list funced_update_flaglist(data); break; // Edit a line case GAD_FUNCED_LISTER: // Get selected node node=Att_FindNode(data->func_display_list,msg.Code); // Is this the node we're already editing? if (node==data->edit_node) break; // If we're editing another one, store its contents if (data->edit_node) funced_end_edit(data,data->edit_node,0,0); // Start editing this entry data->edit_node=node; funced_start_edit(data); break; // Return pressed in edit line case GAD_FUNCED_EDIT: // See if we were editing something if (data->edit_node) { // Stop editing funced_end_edit(data,data->edit_node,END_DISABLE,msg.Qualifier); data->edit_node=0; } break; // New entry case GAD_FUNCED_NEW_ENTRY: case GAD_FUNCED_INSERT_ENTRY: // Create new entry functioned_copy_line(data,0,gadgetid,0); break; // Delete entry case GAD_FUNCED_DELETE_ENTRY: // Check we were editing something if (!data->edit_node) break; // Stop editing (signal delete) funced_end_edit(data,data->edit_node,END_DISABLE|END_DELETE,0); data->edit_node=0; break; // Function type case GAD_FUNCED_FUNCTION_TYPE: // Check we were editing something if (!data->edit_node) break; // Store type ((FunctionEntry *)data->edit_node->data)->type=msg.Code; // Disable popup button if no functions DisableObject( data->objlist, GAD_FUNCED_EDIT_GLASS, (msg.Code==INST_COMMAND && !data->startup->func_list)); break; // Glass gadget case GAD_FUNCED_EDIT_GLASS: // Check we were editing something if (data->edit_node) { char buffer[256]; // Put up requester if (!(funced_command_req( data, buffer, ((FunctionEntry *)data->edit_node->data)->type))) break; // Insert string in edit line funced_edit_insertstring( data->objlist, GAD_FUNCED_EDIT, buffer, DOpusBase,(struct Library *)IntuitionBase); } break; // Argument list case GAD_FUNCED_EDIT_ARGUMENT: // Check we were editing something if (data->edit_node) { char buffer[80]; // Put up requester if (!(funced_command_req( data, buffer, -1))) break; // Insert string in edit line funced_edit_insertstring( data->objlist, GAD_FUNCED_EDIT, buffer, DOpusBase,(struct Library *)IntuitionBase); } break; // Export case MENU_FUNCED_EXPORT_ASCII: case MENU_FUNCED_EXPORT_CMD: // Got file requester? if (WINREQUESTER(data->window)) { struct TagItem tags[6]; struct FileRequester *req=WINREQUESTER(data->window); // Show busy pointer SetWindowBusy(data->window); // File requester tags tags[0].ti_Tag=ASLFR_Window; tags[0].ti_Data=(ULONG)data->window; tags[1].ti_Tag=ASLFR_TitleText; tags[1].ti_Data=(ULONG)GetString(startup->locale,MSG_FUNCED_SELECT_FILE); tags[2].ti_Tag=ASLFR_Flags1; tags[2].ti_Data=FRF_DOSAVEMODE|FRF_PRIVATEIDCMP; tags[3].ti_Tag=ASLFR_Flags2; tags[3].ti_Data=FRF_REJECTICONS; tags[4].ti_Tag=(gadgetid==MENU_FUNCED_EXPORT_CMD)?ASLFR_InitialDrawer:TAG_DONE; tags[4].ti_Data=(ULONG)"DOpus5:Commands"; tags[5].ti_Tag=TAG_DONE; // Show filerequester if (AslRequest(req,tags)) { // Build filename strcpy(data->buffer,req->fr_Drawer); AddPart(data->buffer,req->fr_File,256); // Store changes in function funced_store_edits(data); // Do export if (gadgetid==MENU_FUNCED_EXPORT_CMD) function_export_cmd(data->buffer,0,data->function); else L_FunctionExportASCII(data->buffer,0,data->function,startup->a4); } // Remove busy pointer ClearWindowBusy(data->window); } break; // Cut/Copy case MENU_FUNCED_CUT: case MENU_FUNCED_COPY: { APTR iff; // Set busy pointer SetWindowBusy(data->window); // Open clipboard if ((iff=IFFOpen((char *)0,IFF_CLIP_WRITE,ID_OPUS))) { // Stop editing funced_end_edit(data,data->edit_node,END_DISABLE,0); data->edit_node=0; // Store changes in function funced_store_edits(data); // Save function SaveFunction(iff,data->function); // Close clipboard IFFClose(iff); } // Just copy, not cut? if (gadgetid==MENU_FUNCED_COPY) { // Clear busy pointer ClearWindowBusy(data->window); break; } // Fall through, paste null function } // Paste case MENU_FUNCED_PASTE: { Cfg_Function *func=0; // Set busy pointer SetWindowBusy(data->window); // End any edit funced_end_edit(data,data->edit_node,END_DISABLE,0); data->edit_node=0; // Paste? if (gadgetid==MENU_FUNCED_PASTE) { APTR iff; // Open clipboard if ((iff=IFFOpen((char *)0,IFF_CLIP_READ,ID_OPUS))) { // Find function if (IFFNextChunk(iff,ID_FUNC)) { // Read function func=ReadFunction(iff,0,0,0); } // Close clipboard IFFClose(iff); } // No valid function? if (!func) { // Flash error DisplayBeep(data->window->WScreen); ClearWindowBusy(data->window); break; } } // Detach existing list SetGadgetChoices(data->objlist,GAD_FUNCED_FLAGS,(APTR)~0); // Clear function list Att_RemList(data->function_list,REMLIST_SAVELIST|REMLIST_FREEDATA); // Free existing instructions FreeInstructionList(data->function); // Rebuild display list funced_build_display(data); // Clear flags data->function->function.flags=0; funced_update_flaglist(data); // Clear key data->function->function.code=0xffff; SetGadgetValue(data->objlist,GAD_FUNCED_KEY,0); // Clear label if (startup->flags&FUNCEDF_LABEL) { data->label[0]=0; SetGadgetValue(data->p_objlist,GAD_FUNCED_LABEL,0); } // Paste function in? if (func) { short type; // Save type type=data->function->function.func_type; // Copy function in CopyFunction(func,0,data->function); data->function->function.func_type=type; // Free copied function FreeFunction(func); // Initialise gadgets funced_init_gads(data); } // Clear busy pointer ClearWindowBusy(data->window); } break; // Use case GAD_FUNCED_USE: success=1; // Cancel case GAD_FUNCED_CANCEL: break_flag=1; break; } break; // Key press case IDCMP_RAWKEY: // Help? if (msg.Code==0x5f && !(msg.Qualifier&VALID_QUALIFIERS)) { // Set busy pointer SetWindowBusy(data->window); // Send help command IPC_Command(startup->main_owner,IPC_HELP,(1<<31),"Function Editor",0,REPLY_NO_PORT); // Clear busy pointer ClearWindowBusy(data->window); } break; // BOOPSI message case IDCMP_IDCMPUPDATE: { struct TagItem *tags=(struct TagItem *)msg.IAddress; short item; // Check ID if (GetTagData(GA_ID,0,tags)!=GAD_FUNCED_LISTER) break; // Get item if ((item=GetTagData(DLV_DragNotify,-1,tags))!=-1) { // Start the drag config_drag_start(&data->drag,data->func_display_list,item,tags,TRUE); } } break; // Ticks case IDCMP_INTUITICKS: ++data->drag.tick_count; break; } // Reply to any outstanding message if (gmsg) ReplyWindowMsg(gmsg); } } // AppMessage if (data->appwindow) { struct AppMessage *msg; while ((msg=(struct AppMessage *)GetMsg(data->appport))) { // Make sure window is active ActivateWindow(data->window); // Handle message funced_appmsg(data,msg); ReplyMsg((struct Message *)msg); } } // Check break flag if (break_flag) break; // Wait for message Wait(waitbits); } // Restore CD if (lock) UnLock(CurrentDir(lock)); // Edit successful? if (success) { FunctionReturn ret; // Store changes in function funced_store_edits(data); // Fill out return data ret.object=startup->object; ret.object_flags=startup->object_flags; ret.function=data->function; // Send new function back IPC_Command(startup->owner_ipc,FUNCTIONEDIT_RETURN,0,&ret,0,REPLY_NO_PORT); } // End any drag in progress functioned_end_drag(data,0); // Free edit function FreeFunction(data->function); // Close window RemoveAppWindow(data->appwindow); CloseConfigWindow(data->window); // Close application port if (data->appport) { struct Message *msg; while ((msg=GetMsg(data->appport))) ReplyMsg(msg); DeleteMsgPort(data->appport); } // Say goodbye IPC_Goodbye(ipc,startup->owner_ipc,startup->object_flags); // Delete IPC data Forbid(); IPC_Free(ipc); // Free data funced_cleanup(data); FreeVec(startup); }
// Receive edit from function editor short filetypeed_receive_edit( filetype_ed_data *data, FunctionReturn *ret) { Cfg_Function *function=0; Cfg_Function *func_copy=0; BOOL no_func=0,icon=0; func_node *fndata=0; short success=0; // Is the new function empty? if (IsListEmpty((struct List *)&ret->function->instructions)) no_func=1; // Try to copy the new function if (no_func || (func_copy=CopyFunction(ret->function,0,0))) { // Icon menu? (this is a bit kludgy) if (ret->object_flags>15) { Att_Node *node; // Go through icon list for (node=(Att_Node *)data->icon_list->list.lh_Head; node->node.ln_Succ; node=(Att_Node *)node->node.ln_Succ) { // Match function if (((func_node *)node->data)->func==(Cfg_Function *)ret->object_flags) { // Get function pointer function=(Cfg_Function *)ret->object_flags; break; } } icon=1; } // Otherwise, find the function we want to replace else function=FindFunctionType(&data->type->function_list,ret->object_flags); // Add new function to the list if (func_copy) { // Fix type if (!icon) func_copy->function.func_type=ret->object_flags; // Add to list, in same position if applicable if (function) Insert(&data->type->function_list,&func_copy->node,&function->node); else AddTail(&data->type->function_list,&func_copy->node); } // Free old function if (function) { // Remove function and free it Remove(&function->node); FreeFunction(function); } // Store for icon menu if (fndata) fndata->func=func_copy; success=(icon)?2:1; } return success; }
// Do a filetype on a function (? :-) void function_filetype(FunctionHandle *handle) { Cfg_Filetype *type,*last_type=0; Cfg_Function *func,*type_function=0,*old_function; struct List filechange_list; struct Node *node,*next=0; unsigned short qual; // Extract qualifier qual=(handle->data>>16)&0xffff; handle->data&=0xffff; // Backup function pointer old_function=handle->function; // Lock filetype list lock_listlock(&GUI->filetypes,FALSE); // Steal the filechange list NewList(&filechange_list); for (node=handle->filechange.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&filechange_list,node); } // Got arguments? if (handle->args) { struct ArgArrayEntry *arg; // Go through list for (arg=(struct ArgArrayEntry *)handle->args->aa_List.mlh_Head; arg->ae_Node.mln_Succ; arg=(struct ArgArrayEntry *)arg->ae_Node.mln_Succ) { // Match filetype for this file if (!(type=filetype_identify(arg->ae_String,handle->data,0,qual))) { // Couldn't match. Was this a drag & drop operation? if (handle->flags&FUNCF_DRAG_DROP) { // Use "default" filetype (copy) type=default_filetype; } } // Got filetype? if (type) { // Get appropriate function if ((func=FindFunctionType(&type->function_list,handle->data))) { ExternalEntry *entry; // Different to the last type? if (last_type && type!=last_type) { // Anything in the external list? if (!(IsListEmpty((struct List *)&handle->external_list)) && type_function) { Cfg_Function *copy; // Initialise handle function function_handle_init(handle,1); // Copy the function if ((copy=CopyFunction(type_function,handle->memory,0))) { // Set function pointer handle->function=copy; // Unlock the filetype list unlock_listlock(&GUI->filetypes); // Run function function_run_function(handle); // Free the function FreeFunction(copy); // Lock filetype list again lock_listlock(&GUI->filetypes,FALSE); // Steal new filechanges for (node=handle->filechange.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&filechange_list,node); } } // Clear external list NewList((struct List *)&handle->external_list); } } // Save type pointer last_type=type; // Save function pointer type_function=func; // Create a new external entry if ((entry=new_external_entry(handle,arg->ae_String))) { // Add to external entry list AddTail((struct List *)&handle->external_list,(struct Node *)entry); } } } } } // Anything left in the external list? if (!(IsListEmpty((struct List *)&handle->external_list)) && type_function) { Cfg_Function *copy; // Initialise handle function function_handle_init(handle,1); // Copy the function if ((copy=CopyFunction(type_function,handle->memory,0))) { // Set function pointer handle->function=copy; // Unlock the filetype list unlock_listlock(&GUI->filetypes); // Run function function_run_function(handle); // Free the function FreeFunction(copy); // Lock filetype list again lock_listlock(&GUI->filetypes,FALSE); // Steal new filechanges for (node=handle->filechange.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&filechange_list,node); } } } // Unlock the filetype list unlock_listlock(&GUI->filetypes); // Restore function pointer handle->function=old_function; // Copy filechange list back for (node=filechange_list.lh_Head;node->ln_Succ;node=next) { next=node->ln_Succ; Remove(node); AddTail(&handle->filechange,node); } }