/* * fontMenu * creates (and handles) a hierarchical font menu * * v. 1.00 (22 August 1993) * * © 1993-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "wimp.h" #include "fontMenu.h" #include "msgs.h" #include "werr.h" #include "wimpt.h" #include "menuExt.h" #include "buffer.h" #include #include "font.h" #include "visdelay.h" #include "win.h" #include "utils.h" #include #include static BOOL fontMenu__created; static menu fontMenu__menu; static char fontMenu__oldFontPath[256]; static BOOL fontMenu__anyFonts; static BOOL fontMenu__includeSystem; static int fontMenu__tick1=-1; static int fontMenu__tick2=-1; /* * char *fontMenu__fontFamily(char *fontname) * * Use * Returns the family name of the given font. * * Parameters * char *fontname == the name of the font. * * Returns * The family name of the font (i.e. returns "Trinity" for "Trinity.Medium") * as a pointer to a read-only internal static object. */ static char *fontMenu__fontFamily(char *fontname) { char *fontFamily=buffer_find(); int index=0; char c=fontname[index]; while (c!='.' && c>31) { fontFamily[index++]=c; c=fontname[index]; } fontFamily[index]='\0'; return (fontFamily); } /* * char *fontMenu__fontLeaf(char *fontname) * * Use * Returns the leafname of the font (i.e. for "Trinity.Bold.Italic", it * returns "Bold.Italic"). If there is no leafname, it returns * "(Regular)". * * Parameters * char *fontname == the font name * * Returns * A pointer to the leafname (to an internal static object) */ static char *fontMenu__fontLeaf(char *fontname) { char *fontLeaf=buffer_find(); int index=0; int outi=0; char c=fontname[index]; BOOL stopHere=FALSE; while (!stopHere) { index++; if (c<32) return (msgs_lookup("fontmRF:(Regular)")); else if (c=='.') stopHere=TRUE; c=fontname[index]; } while (c>31) c=fontLeaf[outi++]=fontname[index++]; fontLeaf[outi-1]='\0'; return (fontLeaf); } /* * void fontMenu__handleSubmenu(char *buffer,int *count,menu sub) * * Use * Creates one of those submenus for the font menu. * * Parameters * char *buffer == a buffer to store font names * int *count == pointer to the current font count * menu sub == the submenu handle */ static void fontMenu__handleSubmenu(char *buffer,int *count,menu sub) { char newbuff[50]; char gadbuff[50]; strcpy(newbuff,buffer); wimpt_noerr(font_list(buffer,count)); while ( strcpy(gadbuff,fontMenu__fontFamily(buffer)), *count!=-1 && strcmp(gadbuff,fontMenu__fontFamily(newbuff))==0 ) { menu_extend(sub,fontMenu__fontLeaf(buffer)); strcpy(newbuff,buffer); wimpt_noerr(font_list(buffer,count)); } } /* * menu fontMenu_createFontMenu(BOOL includeSystem) * * Use * Creates a hierarchical font menu and returns a handle. If the menu is * out-of-date it will be recreated, if not the old handle will be * returned. You must call this before using routines such as * fontMenu_make() (so that the system knows whether you want to use a * menu containing the system font or not). The returned pointer will be * NULL if there are no fonts. * * Parameters * BOOL includeSystem == whether you want to include a 'System font' item * * Returns * A menu handle for the menu. */ menu fontMenu_createFontMenu(BOOL includeSystem) { char *fontpath=getenv("Font$Path"); int fontCount=0; char currentfont[50]; char lastTicked[50]; int subIndex=1; menu submenu; if (fontMenu__includeSystem!=includeSystem && fontMenu__created==TRUE) { fontMenu__created=FALSE; menu_dispose(&fontMenu__menu,TRUE); fontMenu__menu=0; } fontMenu__includeSystem=includeSystem; if (fontpath) fontMenu__anyFonts=TRUE; else fontMenu__anyFonts=FALSE; if (fontMenu__created==TRUE && strcmp(fontpath,fontMenu__oldFontPath)==0) return (fontMenu__menu); visdelay_begin(); if (fontMenu__created==TRUE) { strcpy(lastTicked,fontMenu_fontname(fontMenu__tick1,fontMenu__tick2)); menu_dispose(&fontMenu__menu,TRUE); } if (fontMenu__anyFonts==FALSE) { visdelay_end(); if (includeSystem==FALSE) { werr(FALSE,msgs_lookup("fontmNF:No fonts available.")); fontMenu__created=FALSE; return (0); } else { fontMenu__menu=menu_new ( msgs_lookup("fontmFT:Fonts"),msgs_lookup("fontmSF:System font") ); fontMenu__created=TRUE; return (fontMenu__menu); } } strcpy(fontMenu__oldFontPath,fontpath); wimpt_noerr(font_list(currentfont,&fontCount)); if (includeSystem) { fontMenu__menu=menu_new ( msgs_lookup("fontmFT:Fonts"),msgs_lookup("fontmSF:System font") ); menu_extend(fontMenu__menu,fontMenu__fontFamily(currentfont)); subIndex++; } else if (fontCount==-1) { werr(FALSE,msgs_lookup("fontmNF:No fonts available.")); fontMenu__created=FALSE; return (0); } else { fontMenu__menu=menu_new ( msgs_lookup("fontmFT:Fonts"),fontMenu__fontFamily(currentfont) ); } if (!fontMenu__menu) { werr ( FALSE, msgs_lookup("fontmNEM:Not enough memory to create font menu.") ); return (0); } while (fontCount!=-1) { submenu=menu_new ( fontMenu__fontFamily(currentfont), fontMenu__fontLeaf(currentfont) ); if (submenu) { fontMenu__handleSubmenu(currentfont,&fontCount,submenu); menuExt_submenu(fontMenu__menu,subIndex++,submenu); if (fontCount!=-1) menu_extend(fontMenu__menu,fontMenu__fontFamily(currentfont)); } } fontMenu__tick1=-1; if (fontMenu__created) fontMenu_tickGivenName(lastTicked); visdelay_end(); fontMenu__created=TRUE; return (fontMenu__menu); } /* * menu fontMenu(BOOL includeSystem) * * Use * Compatibility. Don't use this function. */ menu fontMenu(BOOL includeSystem) { menu f=fontMenu_createFontMenu(includeSystem); if (!f) exit(0); return (f); } /* * char *fontMenu_fontname(int item1,int item2) * * Use * Returns the font name given by the the menu hit passed. Example code: * * switch (hit[n]) * { * ... * case FONTMENU: * { * char *fontname=fontMenu_fontname(hit[n+1],hit[n+2]); * ... * } * break; * ... * } * * Type promotion does the rest! If the hits give a silly result, then a * null string (not a null pointer!) is returned. * * You should check for the system font yourself (hit[n+1]==1). * * Parameters * int item1 == the item number in the main menu * int item2 == the item number in the submenu * * Returns * A pointer to a read-only string. */ char *fontMenu_fontname(int item1,int item2) { int hits[3]; char *buffer=buffer_find(); char *reg; if (item1==1 && item2==0 && fontMenu__includeSystem==TRUE) return (msgs_lookup("fontmSF:System font")); if (item1==-1) return (""); hits[0]=item1-1; if (item2==0) hits[1]=0; else hits[1]=item2-1; hits[2]=-1; wimpt_noerr(wimp_decode_menu ( (wimp_menustr *)menu_syshandle(fontMenu__menu), hits, buffer )); utils_ctermToNterm(buffer); reg=strstr(buffer,msgs_lookup("fontmRF:(Regular)")); if (reg) *(reg-1)='\0'; return (buffer); } /* * void fontMenu_submenu(BOOL includeSystem) * * Use * Opens a font menu as the submenu of another menu. * * Parameters * BOOL includeSystem == whether we need to include a system font item. */ void fontMenu_submenu(BOOL includeSystem) { wimp_eventstr *e=wimpt_last_event(); int x=e->data.msg.data.words[1]; int y=e->data.msg.data.words[2]; if ( (e->e!=wimp_ESEND && e->e!=wimp_ESENDWANTACK) || e->data.msg.hdr.action!=wimp_MMENUWARN ) return; if (win_anyWindows()==FALSE) { werr ( FALSE, msgs_lookup("fontmTMWS:Too many windows - " "%s could not create submenu."), wimpt_programname() ); } else { visdelay_begin(); fontMenu(includeSystem); wimpt_noerr(wimp_create_submenu ( (wimp_menustr *)menu_syshandle(fontMenu__menu), x, y )); visdelay_end(); } } /* * wimp_menuitem *fontMenu__menuItem(wimp_menustr *m,int item) * * Use * Returns a pointer to the menu item given. * * Parameters * wimp_menustr *m == the menu handle * int item == the item number (starting at one) * * Returns * A pointer to the correct menu item structure. */ static wimp_menuitem *fontMenu__menuItem(wimp_menustr *m,int item) { return ((wimp_menuitem *)(m+1)+item-1); } /* * char *fontMenu__menuText(wimp_menustr *m,int item,char *buffer) * * Use * Returns the text of a menu item. * * Parameters * wimp_menustr *m == the menu handle * int item == the item number (1 upwards) * char *buffer == buffer in which to put the string * * Returns * A pointer to the menu item's text (may or may not be in buffer) */ static char *fontMenu__menuText(wimp_menustr *m,int item,char *buffer) { int i; char c; wimp_menuitem *itm=fontMenu__menuItem(m,item); if (itm->iconflags & wimp_INDIRECT) { c=itm->data.indirecttext.buffer[0]; for (i=0;i<254 && c>31;i++) c=buffer[i]=itm->data.indirecttext.buffer[i]; buffer[i]='\0'; } else { c=itm->data.text[0]; for (i=0;i<=11 && c>31;i++) c=buffer[i]=itm->data.text[i]; buffer[i]='\0'; } return (buffer); } /* * wimp_menustr *fontMenu__submenu(wimp_menustr *m,int item) * * Use * Returns the handle of the submenu of a menu item. * * Parameters * wimp_menustr *m == the menu handle * int item == the item number * * Returns * A pointer to the submenu */ static wimp_menustr *fontMenu__submenu(wimp_menustr *m,int item) { return (fontMenu__menuItem(m,item)->submenu); } /* * void fontMenu_findFont(char *name,int *item1,int *item2) * * Use * Finds a font in the font list. Returns the result in two integers, * which are the menu item numbers in the main font menu and the submenu * respectively. -1 is returned as the first item number if the font * wasn't found. * * Parameters * char *name == the (case sensitive) name of the font. * int *item1 == where to store the first item number. * int *item2 == where to store the second item number. */ void fontMenu_findFont(char *name,int *item1,int *item2) { int i=1; int j; wimp_menustr *m=menu_syshandle(fontMenu__menu); wimp_menustr *s; char *family=fontMenu__fontFamily(name); char *leaf=fontMenu__fontLeaf(name); char buffer[40]; if ( strcmp(name,msgs_lookup("fontmSF:System font"))==0 && fontMenu__includeSystem==TRUE ) { *item1=1; *item2=-1; return; } do { if (strcmp(fontMenu__menuText(m,i,buffer),family)==0) { s=fontMenu__submenu(m,i); j=1; do { if (strcmp(fontMenu__menuText(s,j,buffer),leaf)==0) { *item1=i; *item2=j; return; } j++; } while ((fontMenu__menuItem(s,j-1)->flags&wimp_MLAST)==0); *item1=-1; return; } i++; } while ((fontMenu__menuItem(m,i-1)->flags&wimp_MLAST)==0); *item1=-1; return; } /* * void fontMenu__tickItem(wimp_menustr *m,item i,BOOL onOrOff) * * Use * Ticks a menu item (low-level) * * Parameters * wimp_menustr *m == the menu handle * item i == the menu item * BOOL onOrOff == tick is on or off */ static void fontMenu__tickItem(wimp_menustr *m,int i,BOOL onOrOff) { if (onOrOff) fontMenu__menuItem(m,i)->flags|=wimp_MTICK; else fontMenu__menuItem(m,i)->flags&=~wimp_MTICK; } /* * void fontMenu__doTick(BOOL onOrOff) * * Use * Ticks on or off the current font. * * Parameters * BOOL onOrOff == whether we want to tick or untick the font. */ static void fontMenu__doTick(BOOL onOrOff) { wimp_menustr *m=menu_syshandle(fontMenu__menu); if (fontMenu__tick1==1 && fontMenu__tick2==-1) { fontMenu__tickItem(m,1,onOrOff); } else if (fontMenu__tick1!=-1) { fontMenu__tickItem(m,fontMenu__tick1,onOrOff); fontMenu__tickItem ( fontMenu__submenu(m,fontMenu__tick1), fontMenu__tick2, onOrOff ); } } /* * void fontMenu_tick(int item1,int item2) * * Use * Ticks the item specified. Only one font may be ticked at a time. If * the menu item specified is silly, no item will be ticked. No range * checking is performed. * * Parameters * int item1 == the item number in the main menu * int item2 == the item number in the submenu */ void fontMenu_tick(int item1,int item2) { fontMenu__doTick(FALSE); fontMenu__tick1=item1; fontMenu__tick2=item2; fontMenu__doTick(TRUE); } /* * void fontMenu_tickGivenName(char *name) * * Use * Ticks the item specified by it's name. If the name is silly, no item * will be ticked. * * Parameters * char *name == the font name to tick */ void fontMenu_tickGivenName(char *name) { int i1,i2; fontMenu_findFont(name,&i1,&i2); fontMenu_tick(i1,i2); }