home *** CD-ROM | disk | FTP | other *** search
-
- /* *** filesupp.c ***********************************************************
- *
- * File IO Suite -- Open Requester Routines
- * from Book 1 of the Amiga Programmers' Suite by RJ Mical
- *
- * Copyright (C) 1986, 1987, Robert J. Mical
- * All Rights Reserved.
- *
- * Created for Amiga developers.
- * Any or all of this code can be used in any program as long as this
- * entire copyright notice is retained, ok? Thanks.
- *
- * HISTORY NAME DESCRIPTION
- * ----------- -------------- --------------------------------------------
- * 4 Feb 87 RJ Real release
- * 12 Aug 86 RJ >:-{)* Prepare (clean house) for release
- * 3 May 86 =RJ Mical= Fix prop gadget for both 1.1 and 1.2
- * 1 Feb 86 =RJ Mical= Created this file.
- *
- * *********************************************************************** */
-
-
- #define FILEIO_SOURCEFILE
- #include "fileio.h"
-
-
- /* I think these are silly, but I put them here anyway to avoid compiler
- * warnings.
- */
- VOID InitOpenProp();
- VOID StuffSelectNames();
-
-
-
- /* ======================================================================= */
- /* === ResetText Routines ================================================ */
- /* ======================================================================= */
-
- VOID ResetTextGrunt(info, resetbuffer)
- struct StringInfo *info;
- BOOL resetbuffer;
- /* Reset the string position variables, and reset the buffer itself if
- * resetbuffer is TRUE.
- */
- {
- info->BufferPos = info->DispPos = 0;
- if (resetbuffer) info->Buffer[0] = '\0';
- }
-
- VOID ResetNameText(resetbuffer)
- BOOL resetbuffer;
- {
- ResetTextGrunt(&OpenNameTextInfo, resetbuffer);
- }
-
- VOID ResetDrawerText(resetbuffer)
- BOOL resetbuffer;
- {
- ResetTextGrunt(&OpenDrawerTextInfo, resetbuffer);
- }
-
- VOID ResetDiskText(resetbuffer)
- BOOL resetbuffer;
- {
- ResetTextGrunt(&OpenDiskTextInfo, resetbuffer);
- }
-
-
-
- /* ======================================================================= */
- /* === WarmStart Initializer ============================================= */
- /* ======================================================================= */
-
- VOID WarmStartFileIO(fileio)
- struct FileIOSupport *fileio;
- /* This routine establishes a lock on the current disk and drawer,
- * resets all of the subsystem control variables,
- * gets the file names for the current disk and drawer,
- * initializes the proportional gadget,
- * and then refreshes the requester.
- */
- {
- ULONG lock;
-
- /* If the fileio already had a lock, release it before proceeding */
- if (FlagIsSet(fileio->Flags, LOCK_GOTTEN))
- {
- UnLock(fileio->DOSLock);
- ClearFlag(fileio->Flags, LOCK_GOTTEN);
- fileio->DOSLock = OpenSaveLock;
- CurrentDir(OpenSaveLock);
- }
-
- /* Build the lock name using the current disk and drawer names */
- if (StringLength(&fileio->DiskName[0]))
- CopyString(&OpenLockName[0], &fileio->DiskName[0]);
- else
- CopyString(&OpenLockName[0], CurrentVolumeName());
- ConcatString(&OpenLockName[0], &fileio->DrawerName[0]);
-
- /* Can we get a lock on this name? */
- if (lock = Lock(&OpenLockName[0], ACCESS_READ))
- {
- /* Got it! */
- SetFlag(fileio->Flags, LOCK_GOTTEN);
- fileio->DOSLock = lock;
- CurrentDir(lock);
- }
- else
- {
- /* Hey, bad break, this name just won't do. But the rest of these
- * routines need a valid directory, so go back home.
- */
- Alert(ALERT_BAD_DIRECTORY, OpenReqWindow);
- CopyString(&fileio->DiskName[0], &CurrentDiskString[0]);
- ResetDiskText(FALSE);
- ResetDrawerText(TRUE);
- }
-
- /* Reset the fileio name selection variables */
- fileio->CurrentPick = -1;
- fileio->NameStart = 0;
- fileio->NameCount = 0;
-
- /* Reset the text and gadgets */
- InitOpenProp(TRUE); /* Initialize the prop gadget */
- BuildNameTable(OpenReqFileIO); /* Get the file names */
- StuffSelectNames(-1); /* Display the file names */
- }
-
-
-
- /* ======================================================================= */
- /* === Select Name Routines ============================================== */
- /* ======================================================================= */
-
- VOID BlankSelectText(index)
- SHORT index;
- /* This routine truns the SelectText at index into blanks */
- {
- UBYTE *ptr;
- SHORT blanklength;
-
- ptr = &OpenSelectBuffers[index][0];
- for (blanklength = VISIBLE_SELECT_LENGTH - 1; blanklength; blanklength--)
- *ptr++ = ' ';
- *ptr = '\0';
-
- OpenSelectText[index].FrontPen = 1;
- OpenSelectText[index].BackPen = 0;
- }
-
-
-
- VOID DrawSelectNames()
- {
- struct Layer *layer;
-
- Forbid();
- if (layer = OpenReq->ReqLayer)
- if (layer->rp)
- PrintIText(layer->rp,
- &OpenSelectText[NAME_ENTRY_COUNT - 1],
- OPENSELECT_LEFT, OPENSELECT_TOP);
- Permit();
- }
-
-
-
- VOID StuffSelectNames(refreshcount)
- SHORT refreshcount;
- /* This routine stuffs the Open Requester's filename gadgets with
- * names from the fileio structure, starting from the
- * fileio->NameStart name. If the refreshcount is nonzero, the gadgets
- * will be refreshed too.
- */
- {
- SHORT i, end, bufferpos;
- SHORT length, blanklength;
- UBYTE *ptr, *ptr2;
- struct Remember *remember;
- struct Layer *layer;
-
- if (OpenReqFileIO->NameCount
- > OpenReqFileIO->NameStart + NAME_ENTRY_COUNT)
- end = OpenReqFileIO->NameStart + NAME_ENTRY_COUNT;
- else end = OpenReqFileIO->NameCount;
-
- bufferpos = 0;
-
- /* The current file names are stored in the fileio's Remember list */
- remember = OpenReqFileIO->NameKey;
- for (i = 0; i < OpenReqFileIO->NameStart; i++)
- remember = remember->NextRemember;
-
- for (i = OpenReqFileIO->NameStart; i < end; i++)
- {
- ptr = &OpenSelectBuffers[bufferpos][0];
- ptr2 = remember->Memory;
-
- length = StringLength(ptr2);
- if (length >= VISIBLE_SELECT_LENGTH)
- length = VISIBLE_SELECT_LENGTH - 1;
- blanklength = (VISIBLE_SELECT_LENGTH - 1) - length;
-
- /* By filling up the IntuiText with blanks after the characters,
- * the text, when printed, will overstrike any characters that were
- * there before.
- */
- for ( ; length; length--) *ptr++ = *ptr2++;
- for ( ; blanklength; blanklength--) *ptr++ = ' ';
- *ptr = '\0';
-
- /* If this is the selected text, then use "highlight" pens */
- if (i == OpenReqFileIO->CurrentPick)
- {
- OpenSelectText[bufferpos].FrontPen = -2;
- OpenSelectText[bufferpos].BackPen = -1;
- }
- else
- {
- OpenSelectText[bufferpos].FrontPen = 1;
- OpenSelectText[bufferpos].BackPen = 0;
- }
-
- bufferpos++;
- remember = remember->NextRemember;
- }
-
- /* Now, for all lines that have no entries, fill with blanks */
- for ( ; bufferpos < NAME_ENTRY_COUNT; bufferpos++)
- BlankSelectText(bufferpos);
-
- /* Finally, redraw the lot */
- if (refreshcount)
- {
- Forbid();
- if (layer = OpenReq->ReqLayer)
- if (layer->rp)
- RefreshGList(&OpenSelectNameGadget, OpenReqWindow, OpenReq,
- refreshcount);
- DrawSelectNames();
- Permit();
- }
- }
-
-
-
- VOID SetNameStart()
- /* This little guy sets the NameStart based on the current
- * prop gadget setting.
- */
- {
- if (OpenReqFileIO->NameCount <= NAME_ENTRY_COUNT)
- OpenReqFileIO->NameStart = 0;
- else
- OpenReqFileIO->NameStart = (OpenPropInfo.VertPot
- * (OpenReqFileIO->NameCount - NAME_ENTRY_COUNT + 1)) >> 16;
- }
-
-
-
- VOID StripLastDrawer()
- /* This guy strips the end drawer reference off of the drawer string,
- * which includes nulling out the string if there's only one to strip.
- */
- {
- UBYTE *ptr;
- SHORT index;
-
- ptr = OpenDrawerTextInfo.Buffer;
- index = IndexString(ptr, "/");
- if (index != -1)
- {
- /* OK, there's more than one drawer reference, so get the ptr + index
- * to the last one.
- */
- do
- ptr += (index + 1);
- while ((index = IndexString(ptr, "/")) != -1);
- }
- else index = 0;
- /* Zammo! */
- *(ptr + index) = '\0';
- }
-
-
-
- BOOL DirectoryName()
- /* Returns TRUE if the selected name was a directory-type reference
- * (up or down), else returns FALSE for a normal filename.
- */
- {
- struct Remember *entry;
- SHORT i;
- UBYTE entryflags;
-
- if (OpenReqFileIO->NameCount)
- {
- /* Find the selected entry in the key list */
- entry = OpenReqFileIO->NameKey;
- for (i = OpenReqFileIO->CurrentPick; i > 0; i--)
- entry = entry->NextRemember;
- i = StringLength(entry->Memory) + 1;
- entryflags = *(entry->Memory + i);
-
- if (FlagIsSet(entryflags, NAMED_DIRECTORY | NAMED_PREVIOUS))
- return(TRUE);
-
- /* else just a normal file name was selected, so fall out to ... */
- }
- return(FALSE);
- }
-
-
-
- VOID StuffFileName()
- /* If the selected name is a normal filename, stuffs the filename into the
- * Name gadget. If the selected name is a directory reference,
- * adjusts the drawer gadget accordingly.
- * Returns TRUE if the selected name was a directory-type reference
- * (up or down), else returns FALSE for a normal filename.
- */
- {
- struct Remember *entry;
- SHORT i;
- UBYTE entryflags;
-
- if (OpenReqFileIO->NameCount)
- {
- /* Find the selected entry in the key list */
- entry = OpenReqFileIO->NameKey;
- for (i = OpenReqFileIO->CurrentPick; i; i--)
- entry = entry->NextRemember;
- i = StringLength(entry->Memory) + 1;
- entryflags = *(entry->Memory + i);
-
- if (FlagIsSet(entryflags, NAMED_DIRECTORY))
- {
- /* If there's already a drawer reference, build a proper
- * extension before adding the new to the end.
- */
- if (StringLength(OpenDrawerTextInfo.Buffer))
- ConcatString(OpenDrawerTextInfo.Buffer, "/");
-
- ConcatString(OpenDrawerTextInfo.Buffer,
- entry->Memory + DIR_TEXT_SIZE);
-
- ResetDrawerText(FALSE);
- ResetNameText(TRUE);
- }
- else if (FlagIsSet(entryflags, NAMED_PREVIOUS))
- {
- /* Remove the last drawer reference */
- StripLastDrawer();
- ResetDrawerText(FALSE);
- ResetNameText(TRUE);
- }
- else
- {
- /* Just a normal old file name was selected */
- CopyString(OpenNameTextInfo.Buffer, entry->Memory);
- ResetNameText(FALSE);
- }
- }
- }
-
-
-
- /* ======================================================================= */
- /* === Proportional Gadget Routines ====================================== */
- /* ======================================================================= */
-
- VOID SetOpenPropPot(resetpos)
- BOOL resetpos;
- /* This routine resets the vertical pot of the proportional gadget
- * with respect to the current number of displayable file names.
- */
- {
- LONG slack, result;
-
- slack = OpenReqFileIO->NameCount - NAME_ENTRY_COUNT;
-
- if (slack > 0)
- {
- result = ((LONG)OpenReqFileIO->NameStart << 16) / slack;
- if (result > 0xFFFF) result = 0xFFFF;
- OpenPropInfo.VertPot = result;
- }
- else
- OpenPropInfo.VertPot = 0;
-
- if (resetpos) OpenPropImage.TopEdge = 0;
- }
-
-
-
- VOID InitOpenProp(resetpos)
- BOOL resetpos;
- /* This routine initializes the variable imagery of the proportional
- * gadget and then initializes the gadget's vertical pot.
- * The BOOL arg resetpos describes whether you want the call to
- * SetOpenPropPot() to reset the prop's knob position.
- */
- {
- LONG namecount, height;
- SHORT i, i2;
-
- namecount = OpenReqFileIO->NameCount;
-
- if (namecount <= NAME_ENTRY_COUNT)
- {
- OpenPropInfo.VertBody = 0xFFFF;
- ClearFlag(OpenPropInfo.Flags, FREEVERT);
- height = OPENPROP_MAXHEIGHT;
- }
- else
- {
- OpenPropInfo.VertBody = ((LONG)NAME_ENTRY_COUNT << 16) / namecount;
- SetFlag(OpenPropInfo.Flags, FREEVERT);
- height = (OPENPROP_MAXHEIGHT * NAME_ENTRY_COUNT) / namecount;
- if (height < OPENPROP_MINHEIGHT) height = OPENPROP_MINHEIGHT;
- }
-
- OpenPropImage.Height = height;
- for (i = 0; i < OPENPROP_TOPHEIGHT; i++)
- {
- OpenPropData[i] = OpenPropTop[i];
- OpenPropData[i + height] = OpenPropTop[i + OPENPROP_TOPHEIGHT];
- }
-
- for (i = OPENPROP_TOPHEIGHT; i < height - OPENPROP_BOTTOMHEIGHT; i++)
- {
- OpenPropData[i] = OpenPropBottom[0];
- OpenPropData[i + height] = OpenPropBottom[OPENPROP_BOTTOMHEIGHT];
- }
-
- i2 = 0;
- for (i = height - OPENPROP_BOTTOMHEIGHT; i < height; i++)
- {
- OpenPropData[i] = OpenPropBottom[i2];
- OpenPropData[i + height] = OpenPropBottom[i2 + OPENPROP_BOTTOMHEIGHT];
- i2++;
- }
-
- SetOpenPropPot(resetpos);
- }
-
-
-
-
- /* ======================================================================= */
- /* === Requester Handler Routines ======================================== */
- /* ======================================================================= */
-
- VOID StartOpenRequester()
- /* Called after the requester has been opened. */
- {
- ActivateGadget(&OpenNameTextGadget, OpenReqWindow, OpenReq);
-
- if (FlagIsClear(OpenReqFileIO->Flags, GOOD_FILENAMES))
- WarmStartFileIO(OpenReqFileIO);
- else DrawSelectNames();
- }
-
-
-
- SHORT HandleSelect(y, seconds, micros)
- SHORT y;
- LONG seconds, micros;
- /* This routine accepts that a GADGETDOWN occured at the given
- * pointer y offset. This is translated into the ordinal number of the
- * filename selected by the user, and this is assigned to the
- * CurrentPick variable of the OpenReqFileIO structure.
- * Returns:
- * 1 = DirectoryName() returned TRUE (selection was directory name)
- * 0 = new name selected, DirectoryName() returned FALSE (normal name)
- * -1 = same name selected, double-clicked
- * -2 = same name selected, not double-clicked
- */
- {
- SHORT returnvalue, oldy;
- LONG oldseconds, oldmicros;
-
- y -= (OpenReq->TopEdge + OPENSELECT_TOP);
- y = y / OPEN_LINEHEIGHT;
- y += OpenReqFileIO->NameStart;
- if (y >= OpenReqFileIO->NameCount)
- y = OpenReqFileIO->NameCount - 1;
-
- oldseconds = OpenClickSeconds;
- oldmicros = OpenClickMicros;
- OpenClickSeconds = seconds;
- OpenClickMicros = micros;
-
- oldy = OpenReqFileIO->CurrentPick;
- OpenReqFileIO->CurrentPick = y;
-
- if (DirectoryName())
- {
- returnvalue = 1;
- }
- else
- {
- if (y == oldy)
- {
- /* User has selected the same name again.
- * Was it done quickly enough to count as a
- * double-click selection?
- */
- if (FlagIsClear(OpenReqFileIO->Flags, DOUBLECLICK_OFF)
- && DoubleClick(oldseconds, oldmicros,
- OpenClickSeconds, OpenClickMicros))
- returnvalue = -1;
- else returnvalue = -2;
- }
- else
- {
- /* Do this work, what there is of it, only if the user
- * hasn't reselected an already-selected name.
- */
- returnvalue = 0;
- }
- }
-
- return(returnvalue);
- }
-
-
-
- LONG HandleGadget(gadget, x, y, seconds, micros)
- struct Gadget *gadget;
- SHORT x, y;
- LONG seconds, micros;
- /* This routine handles one gadget selection */
- {
- BOOL softbuild, hardbuild;
- SHORT count;
- LONG returnvalue;
-
- /* softbuild causes the file names to be refreshed.
- * hardbuild causes the entire requester to be reestablished.
- * either or both can be set.
- */
- softbuild = hardbuild = FALSE;
-
- /* count refers to the count that will be sent to StuffSelectNames().
- * The default is 2, as you can see.
- */
- count = 2;
-
- /* If the selection of any gadget causes us to want the requester to
- * go away, set the returnvalue non-zero.
- */
- returnvalue = 0;
-
- switch (gadget->GadgetID)
- {
- case OPENGADGET_SELECTNAME:
- if (OpenReqFileIO->NameCount)
- {
- /* So our big name gadget was selected, eh? Well, which one
- * was the user really pointing at?
- */
- y = HandleSelect(y, seconds, micros);
- if (y < 0)
- {
- /* The user has reselected the old name */
- if (y == -1) returnvalue = -1;
- }
- else
- {
- /* The user has selected a new name */
- StuffFileName();
- softbuild = TRUE;
- if (y == 1) hardbuild = TRUE;
- count = 5;
- }
- }
- break;
- case OPENGADGET_UPGADGET:
- if (OpenReqFileIO->NameStart)
- {
- OpenReqFileIO->NameStart--;
- softbuild = TRUE;
- }
- break;
- case OPENGADGET_DOWNGADGET:
- if (OpenReqFileIO->NameStart + NAME_ENTRY_COUNT
- < OpenReqFileIO->NameCount)
- {
- OpenReqFileIO->NameStart++;
- softbuild = TRUE;
- }
- break;
- case OPENGADGET_PROPGADGET:
- if (OpenReqFileIO->NameCount > NAME_ENTRY_COUNT)
- {
- SetNameStart();
- softbuild = TRUE;
- }
- break;
- case OPENGADGET_NEXTDISK:
- /* Next disk! Wholly mackerel! First, if no "next" then split */
- if (OpenReqFileIO->VolumeCount <= 1) break;
-
- OpenReqFileIO->VolumeIndex++;
- if (OpenReqFileIO->VolumeIndex >= OpenReqFileIO->VolumeCount)
- OpenReqFileIO->VolumeIndex = 0;
- CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName());
- ResetDiskText(FALSE);
- ResetDrawerText(TRUE);
-
- /* Refresh the display so the user can see what's been done, as
- * well as having the display refreshed all over again (hardbuild)
- * below after the new filenames are retrieved.
- */
- softbuild = TRUE;
- count = 5;
-
- /* Intentionally fall into DRAWER/DISKTEXT */
-
- case OPENGADGET_DRAWERTEXT:
- case OPENGADGET_DISKTEXT:
- ResetNameText(TRUE);
- hardbuild = TRUE;
- break;
- default:
- break;
- }
-
- /* These are split intentionally, because setters of hardbuild might
- * want a softbuild done first, to show why a hardbuild is being done!
- */
- if (hardbuild) SetWaitPointer(OpenReqWindow);
- if (softbuild)
- {
- SetOpenPropPot();
- StuffSelectNames(count);
- }
- if (hardbuild)
- WarmStartFileIO(OpenReqFileIO); /* Restart the lock etc. */
-
- return(returnvalue);
- }
-
-
-
- VOID DiskInserted()
- /* This routine is called by the RequesterSupport code whenever a new disk
- * has been inserted. This allows the user to swap disks while the
- * requester is displayed. Unfortunately, I have no way of knowing which
- * disk swapped, so I have to restart the requester more or less.
- * Not too bad, but a little unpleasant.
- */
- {
- SetWaitPointer(OpenReqWindow);
- SetFlag(OpenReqFileIO->Flags, DISK_HAS_CHANGED);
- BuildVolumeTable(OpenReqFileIO);
- CopyString(&OpenReqFileIO->DiskName[0], CurrentVolumeName());
- WarmStartFileIO(OpenReqFileIO);
- }
-
-
-
- VOID PropMouseMoves()
- /* This routine is called by RequesterSupport whenever the mouse moves
- * while a FOLLOWMOUSE gadget is set. The only FOLLOWMOUSE gadget is
- * the prop gadget, so...
- */
- {
- /* ... if there's more names than the number of visible names,
- * then reset the name start and redisplay the names.
- */
- if (OpenReqFileIO->NameCount > NAME_ENTRY_COUNT)
- {
- SetNameStart();
- StuffSelectNames(2);
- }
- }
-
-