home *** CD-ROM | disk | FTP | other *** search
Wrap
/* >$.CLIB.C.menu * * HASWIN Graphics Library * ========================= * * Copyright (C) H.A.Shaw 1990. * Howard A. Shaw. * The Unit for Space Sciences, * Room 165, * Physics Building, * University of Kent at Canterbury. * Canterbury. * Kent. CT2 7NJ * You may use and distribute this code freely, however please leave * it alone. If you find bugs (and there will be many) please contact * me and the master source can be modified. If you keep me informed * of who you give copies of this to then I can get release upgrades * to them. * * routines to control menus. */ #include "includes.h" static int haswin_freemenumem(int *actual) { int *blk; if (!actual) return(HASWIN_FALSE); blk = &actual[7]; /* * blk points at the item data for each menu item in turn. * blk[0] - flags * blk[1] - >= 0x8000: submenu pointer * < 0x7FFF: window handle * -1 nothing * blk[2] - menu icon flags * blk[3] - pointer to menu item name * blk[4] - pointer to validation string(text), or sprite area, or -1 * blk[5] - blk[3] buffer length. */ while ((blk[0]&0x80) != 0x80) { if (blk[1] >= 0x8000) if (!haswin_freemenumem((int *)(blk[1]))) return(HASWIN_FALSE); switch (blk[2] & 0x00000003) { case 0x00000001: /* a text item */ case 0x00000003: /* a text and sprite item */ if ((blk[4]>0x8000) && (!haswin_free((char *)(blk[4])))) { haswin_errorbox("haswin_freemenumen: free fails - &blk[4]"); return(HASWIN_FALSE); } /* FALL THRU */ case 0x00000002: /* a sprite item */ if (!haswin_free((char *)(blk[3]))) { haswin_errorbox("haswin_freemenumen: free fails - &blk[3]"); return(HASWIN_FALSE); } /* FALL THRU */ case 0x00000000: /* not a text or sprite */ break; } blk = &blk[6]; } /* * REMEMBER: the pointer actual should have been created with * haswin_mallocblock(). */ if (!haswin_freeblock(actual)) { haswin_errorbox("haswin_freemenumen: fails - actual"); return(HASWIN_FALSE); } return(HASWIN_TRUE); } menu *haswin_makemenu(menu *mu, char *str, int (*makemenu)(struct menu *), int (*domenu)(char *, struct menu *), int (*message)(buffer *, struct menu *)) { if (!mu) { mu = (menu *)haswin_malloc(sizeof(menu), "haswin_makemenu", "new menu"); mu->menu = 0; mu->actual = 0; mu->extra = 0; mu->makemenu = 0; mu->domenu = 0; mu->message = 0; mu->x = mu->y = 0; mu->topx = mu->topy = 0; mu->ifrom = mu->wfrom = 0; mu->mhelp = mu->whelp = mu->ihelp = 0; } if (str) { mu->menu = haswin_mallocblock(mu->menu, asciilen(str), "haswin_makemenu", "mu->menu"); strcpy(mu->menu, str); } else { if (mu->menu) { haswin_freeblock(mu->menu); mu->menu = 0; } } if (makemenu) mu->makemenu = makemenu; if (domenu) mu->domenu = domenu; if (message) mu->message = message; return(mu); } /* * build a menu. Uses the icon building bits to create the icons * data within the menu. * * A menu is built from a string of the following form... * * [topts]title.(menu)[opts]item.(menu)[opts]item ... * * topts - one of: * &NN - title background colour NN, <sp>, ends. * $NN - title foreground colour NN, <sp>, ends. * *NN - work background colour NN, <sp>, ends. * @NN - work foreground colour NN, <sp>, ends. * >NN - maximum width of menu, <sp>, ends. * <NN - minimum width of menu, <sp>, ends. * ^NN - minimum height between lines, <sp>, ends. * <sp>, - spacer, ignored. * * title - title of menu (12 characters max.) * * item - item name. * * opts - one of: * - - dotted menu seperator above. * _ - dotted menu seperator below. * / - place tick at left. * | - generate menuwarning message. * # - item in inner menu is a window name. * (menu) - inner menu, or window name (must be before options). * * Note that options are passed to haswin_buildiconflags for * processing. This means the following are allowed in a menu * item option list: * <sp>, - spacer, ignored. * T - Text icon. * S - Sprite icon, can be combined with T. * B - icon has border. * < - left adjust text. * > - right adjust text. * F - filled background. * $NN - use antialiased font NN (<sp>, ends). * h - display any sprite 1/2 size. * ? - icon needs help to redraw. * ! - do not select. * * - force selection. * +NN - make icon writable, buffer length NN (<sp>, ends). * ^ - vertical centering. * ~ - don't cancel on selection of another in ESG. * &NN - background colour (<sp>, ends). * @NN - foreground colour (<sp>, ends). * {str} - validation string "str". * [blk] - sprite area control block "blk". * : - everything after is item name. * `font` - use antialiased font called "font". * * NOTE: items in '...' quotes will not be processed, the ' marks * are removed however. * * "str" is a pointer to the string to work from * "width" is a pointer to an integer to return the width of this level * in. * "buf" points to a buffer to use as the working area for this menu. * Buf has been allocated using haswin_mallocblock() above. If not the * memory allocator is going to get VERY pissed off. The int at buf[-1] * is the length of the buffer. NOTE: we must be very careful about * this. If the buffer is too small then we had better reallocate it. */ static int *haswin_buildmenu(char *str, int *width, int *buf) { char *title, *menubuf, *ptr, *ptr1, *data, *menu; char *itemstart, *innerstart, buff[256]; int i, menui, menucnt, flgs, quoted, bracketcnt; int minwidth, gotmaxdata, windowed; int thiswidth, maxwidth, height, maxdata, numstate; int gotmenu12, gotmenu13, gotmenu14, gotmenu15; int charx, chary; window *win; charx = haswin_readvduvariable(VDUVAR_CharXsize); chary = haswin_readvduvariable(VDUVAR_CharYsize); title = menu = data = (char *)haswin_malloc(asciilen(str)+1, "haswin_buildmenu", "menu"); /* make a copy of the menu */ strcpy(title, str); /* remove the title (up to first '.') and move menu to menu start */ while (*menu != '.') menu++; *(menu++) = '\0'; /* scan through menu chopping at '.' or quotes into separate menu items */ ptr = menu; menucnt=1; bracketcnt=0; quoted = 0; while (*ptr) { if (*ptr == '\'') { if (quoted) quoted = HASWIN_FALSE; else quoted = HASWIN_TRUE; } if (!quoted) { if (*ptr == '(') bracketcnt++; else if (*ptr == ')') bracketcnt--; else if ((bracketcnt == 0) && (*ptr == '.')) { *ptr = '\0'; menucnt++; } } ptr++; } /* * at this point menucnt is the number of items in the menu. * try to use "buf" as a buffer for this level of the menu. */ menubuf = (char *)haswin_mallocblock(buf, 28+((menucnt+1)*24)+1, "haswin_buildmenu", "menu buffer"); /* * now scan the title options looking for colour and size info */ gotmenu12 = gotmenu13 = gotmenu14 = gotmenu15 = thiswidth = 0; maxwidth = 1000; minwidth = 0; height = 0; ptr1 = title; numstate = 0; while (*ptr1) { if (quoted) { if (*ptr1 == '\'') quoted = HASWIN_FALSE; } else { switch (*ptr1) { case '\'': quoted = HASWIN_TRUE; break; case ' ': numstate = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': switch (numstate) { case 1: gotmenu12++; menubuf[12]=menubuf[12]*10+(*ptr1)-'0'; break; case 2: gotmenu13++; menubuf[13]=menubuf[13]*10+(*ptr1)-'0'; break; case 3: gotmenu14++; menubuf[14]=menubuf[14]*10+(*ptr1)-'0'; break; case 4: gotmenu15++; menubuf[15]=menubuf[15]*10+(*ptr1)-'0'; break; case 5: maxwidth = maxwidth*10+(*ptr1)-'0'; break; case 6: minwidth = minwidth*10+(*ptr1)-'0'; break; case 7: height = height*10+(*ptr1)-'0'; break; default: goto title_scan_ended; } break; /* title foreground colour */ case '$': menubuf[12] = gotmenu12 = 0; numstate = 1; break; /* title background colour */ case '&': menubuf[13] = gotmenu13 = 0; numstate = 2; break; /* work foreground colour */ case '@': menubuf[14] = gotmenu14 = 0; numstate = 3; break; /* work background colour */ case '*': menubuf[15] = gotmenu15 = 0; numstate = 4; break; case '>': maxwidth = 0; numstate = 5; break; case '<': minwidth = 0; numstate = 6; break; case '^': height = 0; numstate = 7; break; default: goto title_scan_ended; } } ptr1++; } title_scan_ended: if (quoted) haswin_interrorprintf("haswin_buildmenu: no terminating \' quote in menu title %s", title); if (!gotmenu12) menubuf[12] = 7; if (!gotmenu13) menubuf[13] = 2; if (!gotmenu14) menubuf[14] = 13; if (!gotmenu15) menubuf[15] = 0; if (menubuf[12] > 15) { haswin_internalerror("haswin_buildmenu: $: illegal colour"); menubuf[12] = 7; } if (menubuf[13] > 15) { haswin_internalerror("haswin_buildmenu: &: illegal colour"); menubuf[13] = 2; } if (menubuf[14] > 15) { haswin_internalerror("haswin_buildmenu: @: illegal colour"); menubuf[14] = 13; } if (menubuf[15] > 15) { haswin_internalerror("haswin_buildmenu: *: illegal colour"); menubuf[15] = 0; } thiswidth = (asciilen(title)>12) ? 12 : asciilen(title); if (minwidth < thiswidth) minwidth = thiswidth; if (maxwidth < thiswidth) maxwidth = thiswidth; if (minwidth > maxwidth) haswin_internalerror("haswin_buildmenu: max and min widths are odd!"); if (height < chary+4) height = chary + 4; /* * minwidth is the minimum width, the greater of given or the title width. * maxwidth is the maximum width, either 10000000 or given. */ strncpy(menubuf, ptr1, 12); ptr = &(menubuf[28]); ptr1 = menu; /* * now we scan along each ('\0' separated) menu item * using haswin_buildiconflags() to build the main icon bits. */ for (menui=0; menui<menucnt; menui++) { if (menui==menucnt-1) flgs = 0x80; else flgs = 0x00; maxdata = gotmaxdata = 0; numstate = windowed = 0; itemstart = ptr1; innerstart = (char *)0; while (*ptr1) { switch (*ptr1) { case ',': case ' ': numstate = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (numstate == 1) { maxdata = maxdata*10+(*ptr1)-'0'; gotmaxdata++; break; } else goto menu_scan_ended; break; case '+': flgs |= 0x04; maxdata = gotmaxdata = 0; numstate = 1; break; case '\'': /* skip everything between ' ' marks */ while ((*ptr1) && (*ptr1 |= '\'')) ptr1++; break; case '(': ptr1++; innerstart = ptr1; bracketcnt = 1; while ((bracketcnt > 0) && (*ptr1)) { if (*ptr1 == '(') bracketcnt++; else if (*ptr1 == ')') bracketcnt--; ptr1++; } if ((!bracketcnt) && (ptr1[-1] == ')')) *(--ptr1) = '\0'; itemstart = ptr1+1; break; case ':': goto menu_scan_ended; } ptr1++; } menu_scan_ended: haswin_buildiconflags(itemstart, 7, 0, 0, &(((int *)ptr)[2]), buff, 256); for (i=0; ((buff[i]) && (i<256)); i++) { switch (buff[i]) { case '/': flgs |= 0x01; break; case '_': flgs |= 0x02; break; case '-': if (menui > 0) ((int *)ptr)[-6] |= 0x02; break; case '|': flgs |= 0x08; break; case '#': windowed++; break; default: haswin_interrorprintf("haswin_buildmenu: unknown option %c in menu (%s)", buff[i], str); break; } } if (windowed) { if (innerstart) { if ((win=haswin_findwindowname(innerstart)) == (window *)0) { haswin_interrorprintf("haswin_buildmenu: cannot find a window named \"%s\" in item %s", innerstart, itemstart); ((int *)ptr)[1] = -1; } else ((int *)ptr)[1] = win->handle; } else { haswin_interrorprintf("haswin_buildmenu: cannot find a window name in \"()\" in item %s", itemstart); } } else if (innerstart) { if ((buf) && (haswin_validpointer((void *)((int *)ptr)[1]))) ((int *)ptr)[1] = (int)haswin_buildmenu(innerstart, 0, (int *)(((int *)ptr)[1])); else ((int *)ptr)[1] = (int)haswin_buildmenu(innerstart, 0, 0); } else ((int *)ptr)[1] = -1; ((int *)ptr)[0] = flgs; if ((thiswidth=asciilen(ptr1)) > minwidth) minwidth = thiswidth; while (*ptr1) ptr1++; ptr1++; ptr+=24; } if (minwidth > maxwidth) minwidth = maxwidth; ((int *)menubuf)[4] = minwidth*charx; ((int *)menubuf)[5] = height; ((int *)menubuf)[6] = 0; if (width) *width = minwidth+2; if (!haswin_free(title)) haswin_errorbox("haswin_buildmenu: haswin_free() fails"); return((int *)menubuf); } /* * given an icon, window and extra create a correct menu extra field. * This is used by the routine "haswin_createmenu()" and * "haswin_recreatemenu()". */ static char *haswin_createmenuextra(window *win, icon *ic, char *extra) { register char *ptr; window *wptr; /* * we build the extra data for the menu we have. Note that the * max we can add is: */ #define MENU_EXTRA asciilen(".-%s.-(infomation)#:Info.(Action.:/Open.:/Close):Window.((file_load)#!:Load.(file_save)#!:Save.(Options./:Add./:Replace):Options):!Files.(Help on.%c:Icon.%c:Window.%c:Menu):!Help.-:Quit") if ((extra) && (extra[0] != '\0')) { ptr = haswin_malloc(MENU_EXTRA + asciilen(extra), "haswin_createmenuextra", "string"); sprintf(ptr, ".-%s", extra); } else { ptr = haswin_malloc(MENU_EXTRA, "haswin_createmenuextra", "string"); ptr[0] = '\0'; } /* Are we on the icon bar with an Information window to open ? */ if ((ic) && (ic->whandle < 0) && (haswin_flags & HASWIN_FLAGS_INFOWIN)) strcat(ptr, ".(information)#-:Info."); else strcat(ptr, ".-!:Info."); /* do we have an icon with a window to open ? */ if ((ic) && (ic->window)) { if (haswin_getwindowflags(ic->window) & WINDOW_OPEN) strcat(ptr, "(Action./:Open.:Close):Window"); else strcat(ptr, "(Action.:Open./:Close):Window"); } else strcat(ptr, "!:Window"); if ((ic) && (ic->whandle < 0) && (haswin_flags & HASWIN_FLAGS_FILEMENU)) { strcat(ptr, ".(Filing.(file_load)#"); if (!haswin_loadfileroutine) strcat(ptr, "!"); strcat(ptr, ":Load.(file_save)#"); if (!haswin_savefileroutine) strcat(ptr, "!"); strcat(ptr, ":Save.(Options."); if (haswin_fileoptions & HASWIN_OPTIONS_ADD) strcat(ptr, "/:Add.:Replace):Options):Files"); else strcat(ptr, ":Add./:Replace):Options):Files"); } strcat(ptr, ".(Help on."); if ((ic) && (ic->help)) { haswin_menu.ihelp = ic->help; strcat(ptr, "/"); } else { haswin_menu.ihelp = (window *)0; strcat(ptr, "!"); } strcat(ptr, ":Icon."); if (ic) wptr = haswin_findwindowhandle(ic->whandle); else wptr = (window *)0; if (((int)win > 0) && (win->help)) { haswin_menu.whelp = win->help; strcat(ptr, "/"); } else if ((ic) && ((wptr=haswin_findwindowhandle(ic->whandle)) != 0) && (wptr->help)) { haswin_menu.whelp = wptr->help; strcat(ptr, "/"); } else { haswin_menu.whelp = (window *)0; strcat(ptr, "!"); } strcat(ptr, ":Window."); if ((ic) && (ic->menu) && (ic->menu->mhelp)) { haswin_menu.mhelp = ic->menu->mhelp; strcat(ptr, "/"); } else if (((int)win > 0) && (win->menu) && (win->menu->mhelp)) { haswin_menu.mhelp = win->menu->mhelp; strcat(ptr, "/"); } else { haswin_menu.mhelp = (window *)0; strcat(ptr, "!"); } strcat(ptr, ":Menu):Help"); /* do we have an icon with a QUIT ? */ if ((ic) && (ic->flags & ICON_CANQUIT)) strcat(ptr, ".-:Quit"); return(ptr); } /* * given an icon and window create a menu. The icon takes priority * over the window. The 'extra' is added to the menu. The 'user' * routine takes priority over any existing routine. * X and Y are the positions to create the menu at. We adjust so that * X is in the middle of the top level menu. * * The chosing of the text string for the menu is actually the easy bit * haswin_buildmenu() above actually does all the clever stuff. We keep * a record of the window, icon and extra fields we are given in case * we have to recreate the menu later with haswin_recreatemenu() below. * If called with window==0, icon==0 and extra==0 then remove any menu. */ static int haswin_menuwindow = 0; static int haswin_menuicon = 0; static char *haswin_menuextra = 0; int haswin_createmenu(window *win, icon *ic, char *extra, int (*user)(char *, menu *), int x, int y) { static char *menu_total = 0; int i, charx; register char *ptr; char *ptr1; _kernel_swi_regs regs; if ((!win) && (!ic) && (!extra)) { if (haswin_menu.actual != 0) { /* first free the menu we already have */ if (haswin_menu.menu) { if (!haswin_freeblock(haswin_menu.menu)) haswin_internalerror("haswin_createmenu: failed to free haswin_menu.menu"); haswin_menu.menu = 0; } if (!haswin_freemenumem(haswin_menu.actual)) haswin_internalerror("haswin_createmenu: failed to freemenumem haswin_menu.actual"); haswin_menu.actual = 0; } regs.r[1] = -1; return(haswin_swi(HASWIN_Create_menu, ®s)); } /* * we do the menu if... * 1) We have an extra field, * or * 2) We have an ic on the icon bar, with a loadfileroutine or a * savefileroutine, * or * 3) We have an ic with ic->menu or ic->window or ic->help or * ic->flags ICON_CANQUIT, * or * 4) We have a win with win->menu or win->help. */ if (!(extra || (((int)win > 0) && (win->menu || win->help)) || (ic && (((ic->whandle < 0) && (haswin_loadfileroutine || haswin_savefileroutine)) || ic->menu || ic->window || ic->help || (ic->flags&ICON_CANQUIT))) )) return(HASWIN_FALSE); if (haswin_menu.actual != 0) { /* first free the menu we already have */ if (haswin_menu.menu) { if (!haswin_freeblock(haswin_menu.menu)) haswin_internalerror("haswin_createmenu: failed to free haswin_menu.menu"); haswin_menu.menu = 0; } if (!haswin_freemenumem(haswin_menu.actual)) haswin_internalerror("haswin_createmenu: failed to freemenumem haswin_menu.actual"); haswin_menu.actual = 0; } if ((int)win > 0) haswin_menuwindow = win->handle; else haswin_menuwindow = (int)win; if ((int)ic > 0) haswin_menuicon = ic->ihandle; else haswin_menuicon = (int)ic; if (extra) { haswin_menuextra = haswin_realloc(haswin_menuextra, asciilen(extra)+1, "haswin_createmenu", "menu extra string"); strcpy(haswin_menuextra, extra); } else { haswin_menuextra = haswin_realloc(haswin_menuextra, 1, "haswin_createmenu", "menu extra string"); haswin_menuextra[0] = '\0'; } ptr1 = haswin_createmenuextra(win, ic, extra); /* * the "extra, ihelp, mhelp, whelp" fields are now setup. */ if (ic) { /* if we have an icon then we use it */ if (ic->menu) { /* the icon has a menu, so copy it into the one to create */ haswin_menu.x = ic->menu->x; haswin_menu.y = ic->menu->y; haswin_menu.ifrom = ic->menu->ifrom; haswin_menu.wfrom = ic->menu->wfrom; haswin_menu.makemenu = ic->menu->makemenu; haswin_menu.domenu = ic->menu->domenu; haswin_menu.message = ic->menu->message; if (ic->menu->menu) { haswin_menu.menu = haswin_mallocblock(0, asciilen(ic->menu->menu)+1,"haswin_createmenu", "icon menu menu"); strcpy(haswin_menu.menu, ic->menu->menu); } else { haswin_menu.menu = haswin_mallocblock(0, 1, "haswin_createmenu", "icon menu menu"); haswin_menu.menu[0] = '\0'; } } else { /* the icon has no menu, so invent one. Use the icon name as the title. */ ptr = haswin_geticonname(ic); haswin_menu.menu = haswin_mallocblock(0, asciilen(ptr)+1,"haswin_createmenu", "icon name"); strcpy(haswin_menu.menu, ptr); haswin_menu.ifrom = ic->ihandle; haswin_menu.wfrom = ic->whandle; haswin_menu.x = 0; haswin_menu.y = 0; haswin_menu.makemenu = 0; haswin_menu.domenu = 0; haswin_menu.message = 0; } } else if ((int)win > 0) { /* if we have a window then try it */ if (win->menu) { /* the window has a menu, so copy it into the one to create */ haswin_menu.x = win->menu->x; haswin_menu.y = win->menu->y; haswin_menu.ifrom = win->menu->ifrom; haswin_menu.wfrom = win->menu->wfrom; haswin_menu.makemenu = win->menu->makemenu; haswin_menu.domenu = win->menu->domenu; haswin_menu.message = win->menu->message; if (win->menu->menu) { haswin_menu.menu = haswin_mallocblock(0, asciilen(win->menu->menu)+1, "haswin_createmenu", "window menu menu"); strcpy(haswin_menu.menu, win->menu->menu); } else { haswin_menu.menu = haswin_mallocblock(0, 1, "haswin_createmenu", "icon menu menu"); haswin_menu.menu[0] = '\0'; } } else { /* the window has no menu, so invent one. Use the window name as the title. */ ptr = haswin_getwindowname(win); haswin_menu.menu = haswin_mallocblock(0, asciilen(ptr)+1, "haswin_createmenu", "window name"); strcpy(haswin_menu.menu, ptr); haswin_menu.ifrom = -1; haswin_menu.wfrom = win->handle; haswin_menu.x = 0; haswin_menu.y = 0; haswin_menu.makemenu = 0; haswin_menu.domenu = 0; haswin_menu.message = 0; } } else { /* we have neither icon nor window, so create a blank menu */ haswin_menu.menu = haswin_mallocblock(0, 5, "haswin_createmenu", "Menu name"); strcpy(haswin_menu.menu, "Menu"); haswin_menu.ifrom = -1; haswin_menu.wfrom = -1; haswin_menu.x = 0; haswin_menu.y = 0; haswin_menu.makemenu = 0; haswin_menu.domenu = 0; haswin_menu.message = 0; } menu_total = haswin_realloc(menu_total, asciilen(haswin_menu.menu)+asciilen(ptr1)+1, "haswin_createmenu", "final menu string"); sprintf(menu_total, "%s%s", haswin_menu.menu, ptr1); haswin_free(ptr1); i = 0; haswin_menu.actual = haswin_buildmenu(menu_total, &i, haswin_menu.actual); if (user) haswin_menu.domenu = user; charx = haswin_readvduvariable(VDUVAR_CharXsize); haswin_menu.topx = x - i*charx/2; haswin_menu.topy = y; regs.r[1] = (int)haswin_menu.actual; regs.r[2] = haswin_menu.topx; regs.r[3] = haswin_menu.topy; return(haswin_swi(HASWIN_Create_menu, ®s)); } int haswin_recreatemenu() { static char *menu_total = 0; _kernel_swi_regs regs; window *win; char *ptr; icon *ic; if (haswin_menu.actual == 0) return(HASWIN_FALSE); if (!haswin_menu.menu) return(HASWIN_FALSE); if (!haswin_menu.extra) { haswin_menu.extra = haswin_mallocblock(0, 1, "haswin_recreatemenu", "extra field"); haswin_menu.extra[0] = '\0'; } if (haswin_menuwindow) { win = haswin_findwindowhandle(haswin_menuwindow); ic = haswin_findiconhandle(win, haswin_menuicon); } else { win = 0; ic = 0; } ptr = haswin_createmenuextra(win, ic, haswin_menuextra); menu_total = haswin_realloc(menu_total, asciilen(haswin_menu.menu)+asciilen(ptr)+1, "haswin_recreatemenu", "final menu"); sprintf(menu_total, "%s%s", haswin_menu.menu, ptr); haswin_free(ptr); haswin_menu.actual = haswin_buildmenu(menu_total, 0, haswin_menu.actual); regs.r[1] = (int)haswin_menu.actual; regs.r[2] = haswin_menu.topx; regs.r[3] = haswin_menu.topy; return(haswin_swi(HASWIN_Create_menu, ®s)); }