home *** CD-ROM | disk | FTP | other *** search
- /* SetFont 2.0 -
-
- by Dave Haynie
- BIX: hazy
- Usenet: {allegra|caip|ihnp4}!cbmvax!daveh
- Drink: Guiness
-
- BUSINESS (MUNDANE, BUT IMPORTANT):
-
- This program is written by me, Dave Haynie, as mentioned above.
- I have, however, placed it in the PUBLIC DOMAIN. That, of course, means
- that you can do (almost) absolutely anything with it. You may hack it
- to bits, include it with YOUR product, sell it, GIVE IT AWAY, or anything
- else you like. Of course, since anyone else can also give it away, it
- would be foolish to stick your name on it and try to sell it. I really
- would like everyone to give it away, nicely, without being mean about it.
- If you want to use it with your product, do that too, new products for
- the Amiga are generally a good thing for the entire Amiga community. You
- can take bit and pieces and use them in your own programs, or the whole
- thing for that matter. And if you really want to have fun, you can even
- IMPROVE this program, as its far from perfect, and give YOUR version
- away too, if you're so inclined. That's about it for the (mundane)
- business section, let's get on to the (interesting) notes section.
-
- ABOUT IT:
-
- This program is designed to allow you to set the font of a console
- window (or really, a general WorkBench window) to any font, ROM or disk
- based, that you have in mind. This works much better than the first
- version, in that it allows a greater variety of things to be changed
- in the WorkBench. What, you say, a VARIETY of things? Well, lemme
- explain....
-
- First off, something about fonts. Amiga fonts all over the place
- default to one of two ROM fonts, as specified in Preferences. A ROM font
- is just a font that happens to stored in with the KickStart code, instead
- of out on a disk. Since anything ever running on any Amiga can get to
- these fonts, they're used very heavily, perhaps too much. If you've
- ever used the NotePad, however, you will probably have used some other
- fonts. These fonts are available on disk, and in fact, you can use
- FontEd to create a variety of disk fonts for your own use.
-
- Whether disk or ROM, most programs use the Amiga's font management
- utilities, which are part of the KickStart based graphics library. But
- very few folks just look at the graphics library. Most everyone looks
- at Intuition. Intuition manages things like screens and windows, and
- you can write things to both screens and windows. And, perhaps not
- coincidentally, both screens and windows have some idea of what font they
- should use, providing they've been given no special directions toward
- using some other fonts. The screen stores a pointer to a critter called
- a "TextAttr", which is essentially a DESCRIPTOR for a font. A TextAttr
- contains the name of the font, the point size of the font, and a little
- more information related to the font. Both screens and windows also
- contains a graphics structure, called a RastPort, which points to the
- memory used to store the displayed memory. The RastPort sports a pointer
- to a different critter, the "TextFont". The is the actual font, which is
- the result of passing a TextAttr to one of the font opening functions.
-
- In this version I allow you to change the screen's font information,
- like before, but I also know a bit more about the console window now.
- When I open a window within a screen, such as the WorkBench screen,
- it's RastPort gets its default font from the screen's TextAttr font
- descriptor. If this window is going to be a console window, it will
- build a ConUnit, which has its own idea of the current font, based on
- the window's font when it is created. I can use the ROM Kernal SetFont()
- call to change the font of the Window's RastPort. Then I send an "<ESC>c"
- to the console which will reinitialize the ConUnit from the window (and
- also clear the screen....oh well).
-
- I need pointers to the window and screen to do this. Since the
- Window structure contains a pointer to its screen, my goal is to find
- the window associated with the calling console. The best way I've found
- for this is by setting up the current console as an I/O item, then
- calling the DOS Info() function, which will return a pointer to the
- console's window. From this window I can get a the screen pointer and
- the window's RastPort, so the fonts can be put in place. When the
- Screen's TextAttr is changed, I only change the values of that font
- descriptor that the user's asked me to change. Occasionally, this can
- result in a few bytes of unreclaimed memory, as in font names: I have no
- idea how much memory is reserved in the screen's TextAttr structure on
- startup. I use the SetFont() function to set the window's or screen's
- RastPort fonts.
-
- There are a few potential problems with my scheme. First of all,
- many programs are written to support only the topaz 8 (80 column) font
- (sloppy, I know, but that's life). If you're a 60 column user, you've
- probably experienced this before. It's not a problem with the Amiga as
- a whole, since most of the system will adjust itself. But it may be a
- problem with programs that have a fixed idea of what a font should look
- like. Most 80 column fonts work with most applications, and an 80 column
- 8x8 font will work just about everywhere. Some programs, like CLI for
- instance, have trouble with proportionally-spaced fonts. The best thing to
- to is try out the font you like. One final problem is that some
- applications ask the WorkBench screen to close when they start up. It'll
- close if there's nothing else open on it, but when it re-opens, it'll
- restart with the Preferences-selected font, not the SetFont selected font.
- Of course, preferences doesn't support arbitrary fonts (which is why this
- program is even necessary). Oh well, maybe in 1.3? The solution to this
- is to always keep at least one window open, so that WorkBench will never
- be closed on you.
- */
-
- #include <exec/types.h>
- #include <exec/io.h>
- #include <exec/ports.h>
- #include <exec/memory.h>
- #include <graphics/gfxbase.h>
- #include <graphics/text.h>
- #include <graphics/rastport.h>
- #include <libraries/diskfont.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <libraries/diskfont.h>
- #include <intuition/intuitionbase.h>
- #include <stdio.h>
-
- /* ========================================================================= */
-
- /* External things */
-
- extern struct Library *OpenLibrary();
- extern struct TextFont *OpenFont();
- extern struct TextFont *OpenDiskFont();
- extern struct Window *OpenWindow();
-
- extern char *strcat();
- extern char *strcpy();
- extern long strlen();
-
- /* ========================================================================= */
-
- /* Global variables */
-
- struct GfxBase *GfxBase = NULL;
- struct Library *DiskfontBase = NULL;
- struct IntuitionBase *IntuitionBase = NULL;
-
- struct MsgPort portblk = {
- {0L, 0L, NT_MSGPORT, 0, 0L}, 0, -1, 0L,
- {&portblk.mp_MsgList.lh_Tail, 0L, &portblk.mp_MsgList.lh_Head, 0, 0}
- };
- struct MsgPort *port = &portblk;
-
- struct IOStdReq reqblk = {
- {{0L, 0L, 0, 0, 0L}, &portblk, 0}, 0L, 0L, 0, 0, 0, 0L, 0L, 0L, 0L
- };
- struct IOStdReq *request = &reqblk;
-
- struct Window *window = NULL;
- struct Screen *screen = NULL;
-
- /* ========================================================================= */
-
- /* This section contains startup and shutdown functions. */
-
- /* This function opens the required Amiga libraries, devices, and other
- good stuff. It returns TRUE if successful. Graphics, Intuition, and
- DiskFont libraries are opened. The console device is opened and the
- I/O request message port is initialized. I also do a check to make sure
- that the associated Task is really a Process. This is absolutely
- necessary, as some of the functions that I'll be using later are DOS
- functions, which require Processes, not Tasks. */
-
- BOOL OpenUp()
- {
- /* The Libraries */
-
- if ((GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library", 0L)) == NULL) return FALSE;
- if ((DiskfontBase = OpenLibrary("diskfont.library",0L)) == NULL) return FALSE;
- if ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 0L)) == NULL) return FALSE;
-
- /* The Devices */
-
- if ((OpenDevice("console.device", -1L, request, 0L)) != 0L) return FALSE;
- if ((port->mp_SigBit = AllocSignal(-1L)) < 0L) return FALSE;
- port->mp_SigTask = (struct Task *) FindTask((char *) NULL);
- if (port->mp_SigTask->tc_Node.ln_Type != NT_PROCESS) return FALSE;
- return TRUE;
- }
-
- /* This function frees up dynamically opened things, like the devices
- and the libraries, opened above. */
-
- void ShutDown()
- {
- if (request->io_Device != NULL) {
- if (port->mp_SigBit != -1) FreeSignal(port->mp_SigBit);
- CloseDevice(request);
- }
- if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
- if (DiskfontBase != NULL) CloseLibrary(DiskfontBase);
- if (GfxBase != NULL) CloseLibrary(GfxBase);
- }
-
- /* ========================================================================= */
-
- /* Attribute based functions. */
-
- /* This function allocates space for the given font descriptor, converting
- the point size into a numeric form at the same time. */
-
- struct TextAttr *AllocAttr(fontname, pointname)
- char *fontname, *pointname;
- {
- short point;
- char *str;
- struct TextAttr *attr = NULL;
-
- attr = (struct TextAttr *) AllocMem(sizeof(*attr),0L);
-
- if (pointname == NULL) point = 8;
- else point = atoi(pointname);
-
- str = (char *) AllocMem(strlen(fontname)+6L,0L);
- strcpy(str,fontname);
- strcat(str,".font");
- attr->ta_Name = str;
- attr->ta_YSize = point;
- attr->ta_Style = 0;
- attr->ta_Flags = 0;
- return attr;
- }
-
- /* This function frees a TextAttr allocated with AllocAttr(). */
-
- void FreeAttr(attr)
- struct TextAttr *attr;
- {
- if (attr == NULL) return;
- FreeMem(attr->ta_Name, strlen(attr->ta_Name));
- FreeMem(attr,sizeof(*attr));
- }
- /* ========================================================================= */
-
- /* This function allocates a packet and associated info block. It returns
- a pointer to this packet if successful, NULL otherwise. */
-
- struct StandardPacket *AllocInfoPacket()
- {
- struct StandardPacket *pac = NULL;
- struct InfoData *inf = NULL;
-
- pac = (struct StandardPacket *) AllocMem(sizeof(*pac), MEMF_CLEAR);
- if (pac == NULL) return NULL;
- inf = (struct InfoData *) AllocMem(sizeof(*inf), MEMF_CLEAR);
- if (inf == NULL) {
- FreeMem(pac,sizeof(*pac));
- return NULL;
- }
- pac->sp_Msg.mn_Node.ln_Name = (char *) &(pac->sp_Pkt);
- pac->sp_Pkt.dp_Link = &(pac->sp_Msg);
- pac->sp_Pkt.dp_BufAddr = ((ULONG) inf) >> 2;
- pac->sp_Pkt.dp_Type = ACTION_DISK_INFO;
-
- return pac;
- }
-
- /* ========================================================================= */
-
- /* This function gets the Window pointer for the current console. It
- takes the message port for the console. It uses the fact that the I/O
- device's message port points to the process associated with this CLI.
- This process needs a console window, and it should have a pointer to a
- message port for this purpose. We use DOS packets to request an
- InfoData block on this console window. The window pointer is passed
- back as the volume name of the console. We're getting into DOS, so look
- out for BCPL pointers and longword alignment! */
-
- struct Window *GetConsoleWindow(port)
- struct MsgPort *port;
- {
- struct MsgPort *cp; /* Console port */
- struct InfoData *inf; /* Packet data block */
- struct StandardPacket *pac = NULL; /* Packet for DOS request */
- struct Window *w = NULL; /* Resulting Window */
-
- cp = (struct MsgPort *)((struct Process *)port->mp_SigTask)->pr_ConsoleTask;
- if (cp == 0L) return NULL;
-
- if ((pac = AllocInfoPacket()) == NULL) return NULL;
- pac->sp_Pkt.dp_Port = port;
- inf = (struct InfoData *) (((ULONG) pac->sp_Pkt.dp_BufAddr) << 2);
- PutMsg(cp, pac);
- WaitPort(port);
- w = (struct Window *) inf->id_VolumeNode;
- FreeMem(inf, sizeof(*inf));
- FreeMem(pac, sizeof(*pac));
-
- return w;
- }
-
- /* ========================================================================= */
-
- /* This function tries to get a requested font from an attribute descriptor;
- it returns FALSE if the font doesn't exit. */
-
- struct TextFont *GetFont(attr)
- struct TextAttr *attr;
- {
- struct TextFont *font;
-
- if ((font = OpenDiskFont(attr)) != NULL) return font;
- if ((font = OpenFont(attr)) != NULL) return font;
- return NULL;
- }
-
- /* ========================================================================= */
-
- /* The main function */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- short i;
- BOOL printmode = FALSE;
- BOOL mode_screen = FALSE;
- BOOL mode_title = FALSE;
- BOOL mode_window = FALSE;
- struct TextAttr *attr = NULL;
- struct TextFont *newfont, *oldfont;
-
- /* Automatic help command */
-
- if (argc == 1) printmode = TRUE;
- else if (argv[1][0] == '?') {
- printf("SetFont 2.0 by Dave Haynie\n\n");
- printf("Usage: SetFont [fontname [point [place]]], where\n\n");
- printf(" \2331mfontname\2330m is the font's name (e.g. \"topaz\")\n");
- printf(" \2331mpoint\2330m is the point size (default is 8)\n");
- printf(" \2331mplace\2330m pick the place, one or more of:\n");
- printf(" \2331mSCREEN\2330m set the screen font only\n");
- printf(" \2331mTITLES\2330m set the screen titles only\n");
- printf(" \2331mWINDOW\2330m set the window's font only\n\n");
- printf("If no \2331mplace\2330m switch is given, everything is set.\n");
- Exit(10);
- }
-
- /* Process the command-line arguments, AmigaDOS style. */
-
- for (i=3; i<argc; i++)
- if (argv[i][0] == 'T' || argv[i][0] == 't') mode_title = TRUE;
- else if (argv[i][0] == 'S' || argv[i][0] == 's') mode_screen = TRUE;
- else if (argv[i][0] == 'W' || argv[i][0] == 'w') mode_window = TRUE;
- if (!mode_title && !mode_screen && !mode_window)
- mode_title = mode_screen = mode_window = TRUE;
-
- /* First all, we've got to open all the good stuff. */
-
- if (!OpenUp() || (window=GetConsoleWindow(port)) == NULL) {
- ShutDown();
- Exit(10);
- }
-
- /* Process the informational print mode, real simple */
-
- if (printmode) {
- printf("SetFont 2.0 by Dave Haynie\n\n");
- attr = window->WScreen->Font;
- printf("Screen Font: %s (%ld) ", attr->ta_Name, attr->ta_YSize);
- printf("Style %ld, Flags %ld\n", attr->ta_Style, attr->ta_Flags);
- ShutDown();
- Exit(0);
- }
-
- /* Get the attribute and font, where available. */
-
- attr = AllocAttr(argv[1], argv[2]);
- if ((newfont = GetFont(attr)) == NULL) {
- printf("Error: Font not found\n");
- FreeAttr(attr);
- ShutDown();
- Exit(10);
- }
-
- /* Here's where the various options are processed individually. */
-
- /* The screen titling font is changed via a SetFont() call to the
- screen's RastPort. */
-
- if (mode_title) {
- oldfont = window->WScreen->RastPort.Font;
- if (SetFont(&window->WScreen->RastPort,newfont) == 0) CloseFont(oldfont);
- }
-
- /* If the current font is the same font, we can just change the point
- size attribute value. If its a completely new font, the entire
- attribute pointer is reassigned. This may not be necessary, but it
- works this way, and I've had trouble with other schemes. */
-
- if (mode_screen) {
- if (strcmp(window->WScreen->Font->ta_Name,attr->ta_Name) == 0) {
- window->WScreen->Font->ta_YSize = attr->ta_YSize;
- FreeAttr(attr);
- } else
- window->WScreen->Font = attr;
- }
-
- /* The window font is changed via a SetFont() call to the window's
- RastPort, much in the same way that the screen's titling fonts are
- changed. Additionally, the console device must be reset to force
- the ConUnit to be rebuit, which draws the new font from the
- window. */
-
- if (mode_window) {
- oldfont = window->RPort->Font;
- if (SetFont(window->RPort,newfont) != 0L) CloseFont(oldfont);
- printf("\033c");
- }
- CloseFont(newfont);
- ShutDown();
- Exit(0);
- }
-
-