Add support for fetching more results.

This commit is contained in:
Stephen Heumann 2019-04-18 22:58:57 -05:00
parent 567c60040e
commit ef301fd7fc
8 changed files with 150 additions and 53 deletions

View File

@ -84,14 +84,7 @@ static void HandleEvent(int eventCode, WmTaskRec *taskRec) {
case wInControl:
switch (taskRec->wmTaskData4) {
case searchButton:
DoSearch();
break;
case forIIGSRadio:
gsDisksOnly = true;
break;
case forAnyAppleIIRadio:
gsDisksOnly = false;
DoSearch(false);
break;
case mountDiskButton:

View File

@ -23,11 +23,15 @@
#include "browserwindow.h"
#include "diskbrowser.h"
#include "browserevents.h"
#include "disksearch.h"
/* Rectangles outlining the buttons in the style of "default" buttons */
static Rect searchRect = {8, 305, 26, 414};
static Rect mountRect = {150, 301, 168, 414};
static char showMoreString[] = "\pShow More";
static char mountDiskString[] = "\pMount Disk";
/* Has the resource file been opened? (True while window is displayed.) */
static Boolean resourceFileOpened;
@ -48,6 +52,9 @@ static CtlRecHndl searchButtonHandle;
/* Target control ID last time we checked */
static unsigned long lastTargetCtlID = 0;
/* Is "More Results" selected in the disk list? */
static boolean moreResultsSelected = false;
static void DrawContents(void);
static void DrawButtonOutlines(boolean justChanged);
@ -109,8 +116,18 @@ void ShowBrowserWindow(void) {
wantToOpenWindow = 0;
moreResultsSelected = false;
InitEventState();
diskList = malloc(DISK_LIST_MAX_LENGTH * sizeof(*diskList));
if (diskList == NULL) {
CloseWindow(window);
windowOpened = false;
window = NULL;
goto cleanup;
}
cleanup:
if (resourceFileOpened && !windowOpened) {
CloseResourceFile(resourceFileID);
@ -127,9 +144,6 @@ void CloseBrowserWindow(void) {
CloseWindow(window);
windowOpened = false;
window = NULL;
/* reset state */
gsDisksOnly = true;
}
if (resourceFileOpened) {
@ -137,10 +151,9 @@ void CloseBrowserWindow(void) {
resourceFileOpened = false;
}
if (json) {
json_value_free(json);
json = NULL;
}
free(diskList);
FreeJSON();
}
#pragma databank 0
@ -202,7 +215,23 @@ void UpdateControlState(void) {
}
/* Only allow "Mount Disk" to be clicked if there is a disk selected */
if (NextMember2(0, (Handle)disksListHandle) != 0) {
int currentSelection = NextMember2(0, (Handle)disksListHandle);
if (currentSelection != 0) {
if (diskList[currentSelection-1].memPtr == moreResultsString) {
if (!moreResultsSelected) {
SetCtlMoreFlags(GetCtlMoreFlags(mountButtonHandle) & 0xFFFC,
mountButtonHandle);
SetCtlTitle(showMoreString, (Handle)mountButtonHandle);
moreResultsSelected = true;
}
} else {
if (moreResultsSelected) {
SetCtlMoreFlags(GetCtlMoreFlags(mountButtonHandle) & 0xFFFC,
mountButtonHandle);
SetCtlTitle(mountDiskString, (Handle)mountButtonHandle);
moreResultsSelected = false;
}
}
HiliteControl(noHilite, mountButtonHandle);
} else {
HiliteControl(inactiveHilite, mountButtonHandle);

View File

@ -27,24 +27,24 @@ GrafPortPtr window;
/* Is the window open? */
Boolean windowOpened;
/* User preference: IIGS disks or all Apple II disks? */
boolean gsDisksOnly = true;
/* Disks list control */
CtlRecHndl disksListHandle;
/* List of disks, used for list control & mounting disks */
struct diskListEntry diskList[DISK_LIST_LENGTH];
struct diskListEntry *diskList;
/* Do we want to open a window with disk contents? Counts down until ready. */
int wantToOpenWindow = 0;
/* JSON for current disk list (needs to be kept in memory while it's shown) */
json_value *json = NULL;
json_value *json[MAX_PAGES];
/* User ID of this program */
Word myUserID;
/* String for "More Results" (used to identify that list entry) */
char moreResultsString[] = " <More Results>";
/***/
static char menuTitle[] = "\pArchive.org Disk Browser\xC9";

View File

@ -22,15 +22,9 @@ extern GrafPortPtr window;
/* Is the window open? */
extern Boolean windowOpened;
/* User preference: IIGS disks or all Apple II disks? */
extern boolean gsDisksOnly;
/* Disks list control */
extern CtlRecHndl disksListHandle;
/* Length of disks list */
#define DISK_LIST_LENGTH 30
struct diskListEntry {
char *memPtr;
Byte memFlag;
@ -38,14 +32,25 @@ struct diskListEntry {
char *extPtr;
};
/* Maximum number of entries in list */
#define DISK_LIST_MAX_LENGTH (int)(0xFFFF/sizeof(struct diskListEntry))
/* How many results to fetch at a time */
#define PAGE_SIZE 30
#define MAX_PAGES ((DISK_LIST_MAX_LENGTH + PAGE_SIZE - 1) / PAGE_SIZE)
/* List of disks, used for list control & mounting disks */
extern struct diskListEntry diskList[DISK_LIST_LENGTH];
extern struct diskListEntry *diskList;
/* String for "More Results" (used to identify that list entry) */
extern char moreResultsString[];
/* Do we want to open a window with disk contents? Counts down until ready. */
extern int wantToOpenWindow;
/* JSON for current disk list (needs to be kept in memory while it's shown) */
extern json_value *json;
extern json_value *json[MAX_PAGES];
/* User ID of this program */
extern Word myUserID;

View File

@ -123,14 +123,14 @@ resource rPString (forAnyAppleIIRadio) {"Any Apple II"};
resource rControlTemplate (disksList) {
disksList, /* control ID */
{45, 10, 147, 410}, /* control rect */
{45, 10, 147, 386}, /* control rect */
ListControl {{
$0007, /* flags */
$0000, /* flags */
$1400, /* more flags */
0, /* refcon */
0, /* list size */
10, /* List View */
$0000, /* List Type */
$0003, /* List Type */
0, /* List Start */
10, /* ListMemHeight */
13, /* List Mem Size */

View File

@ -24,6 +24,7 @@
#include "diskbrowser.h"
#include "diskmount.h"
#include "browserutil.h"
#include "disksearch.h"
/* Item ID and file extension for the disk image we want to open */
static char *wantedExt;
@ -50,6 +51,11 @@ void DoMount(void) {
}
itemNumber--;
if (diskList[itemNumber].memPtr == moreResultsString) {
DoSearch(true);
return;
}
if (diskList[itemNumber].idPtr == NULL) {
result = 2;
goto errorReturn;

View File

@ -8,8 +8,10 @@
#include <control.h>
#include <list.h>
#include <misctool.h>
#include <quickdraw.h>
#include <qdaux.h>
#include <window.h>
#include <stdio.h>
#include <stdlib.h>
@ -24,22 +26,47 @@
#include "disksearch.h"
#include "browserutil.h"
/* Current position in disk list */
static int diskListPos = 0;
/* Rectangle of the disk list control */
static Rect diskListRect = {45, 10, 147, 386};
/* Current length in disk list */
static int diskListLength = 0;
/* Number of current page of results from server */
int pageNum;
static boolean processDoc(json_value *docObj);
static char *EncodeQueryString(char *queryString);
struct diskListEntry moreResultsEntry = {moreResultsString , 0, "", ""};
static void InsertDiskListEntry(struct diskListEntry *entry);
/* Do a search */
void DoSearch(void) {
void DoSearch(boolean getMore) {
static char queryBuf[257];
static boolean gsDisksOnly = true; /* User preference: IIGS disks only? */
char *searchURL = NULL;
enum NetDiskError result = 0;
int initialDiskListLength = diskListLength;
WaitCursor();
GetLETextByID(window, searchLine, (StringPtr)&queryBuf);
if (!getMore) {
FreeJSON();
GetLETextByID(window, searchLine, (StringPtr)&queryBuf);
gsDisksOnly = (FindRadioButton(window, 2) == 0);
pageNum = 0;
} else {
if (pageNum >= MAX_PAGES - 1) {
InitCursor();
SysBeep();
return;
}
pageNum++;
}
char *queryString = EncodeQueryString(queryBuf+1);
if (queryString == NULL) {
@ -56,8 +83,8 @@ void DoSearch(void) {
"&rows=%i&page=%i&output=json",
gsDisksOnly ? "apple2gs" : "apple2%2A",
queryString,
DISK_LIST_LENGTH,
/*pageNum*/ 0);
PAGE_SIZE,
pageNum + 1);
if (searchURL == NULL) {
result = URL_TOO_LONG;
goto errorReturn;
@ -65,19 +92,25 @@ void DoSearch(void) {
free(queryString);
queryString = NULL;
if (json)
json_value_free(json);
result = ReadJSONFromURL(searchURL, &json);
if (!getMore) {
FreeJSON();
}
result = ReadJSONFromURL(searchURL, &json[pageNum]);
if (result != OPERATION_SUCCESSFUL)
goto errorReturn;
json_value *response = findEntryInObject(json, "response", json_object);
json_value *response =
findEntryInObject(json[pageNum], "response", json_object);
if (response == NULL) {
result = NOT_EXPECTED_CONTENTS;
goto errorReturn;
}
diskListPos = 0;
if (!getMore) {
diskListLength = 0;
} else {
diskListLength--;
}
json_value *docs = findEntryInObject(response, "docs", json_array);
if (docs == NULL) {
result = NOT_EXPECTED_CONTENTS;
@ -85,9 +118,14 @@ void DoSearch(void) {
}
processArray(docs, json_object, processDoc);
diskList[0].memFlag = 0x80;
for (int i = 1; i < DISK_LIST_LENGTH; i++) {
diskList[i].memFlag = 0;
if (!getMore) {
diskList[0].memFlag = 0x80;
}
json_value *numFoundValue =
findEntryInObject(response, "numFound", json_integer);
if (numFoundValue != NULL && numFoundValue->u.integer > diskListLength) {
InsertDiskListEntry(&moreResultsEntry);
}
/* Update state of controls once disk list is available */
@ -97,9 +135,16 @@ void DoSearch(void) {
disksListHandle);
NewList2(NULL, 1, (Ref) diskList, refIsPointer,
diskListPos, (Handle)disksListHandle);
diskListLength, (Handle)disksListHandle);
if (diskListPos > 0) {
if (getMore) {
if (diskListLength >= initialDiskListLength) {
SelectMember2(initialDiskListLength, (Handle)disksListHandle);
ValidRect(&diskListRect);
}
}
if (diskListLength > 0) {
if (FindTargetCtl() != disksListHandle) {
MakeThisCtlTarget(disksListHandle);
CallCtlDefProc(disksListHandle, ctlChangeTarget, 0);
@ -119,7 +164,7 @@ errorReturn:
}
static boolean processDoc(json_value *docObj) {
if (diskListPos >= DISK_LIST_LENGTH)
if (diskListLength >= DISK_LIST_MAX_LENGTH)
return false;
if (docObj == NULL || docObj->type != json_object)
@ -129,10 +174,11 @@ static boolean processDoc(json_value *docObj) {
json_value *ext = findEntryInObject(docObj, "emulator_ext", json_string);
if (id == NULL || title == NULL || ext == NULL)
return true;
diskList[diskListPos].idPtr = id->u.string.ptr;
diskList[diskListLength].idPtr = id->u.string.ptr;
// TODO character set translation
diskList[diskListPos].memPtr = title->u.string.ptr;
diskList[diskListPos++].extPtr = ext->u.string.ptr;
diskList[diskListLength].memPtr = title->u.string.ptr;
diskList[diskListLength].extPtr = ext->u.string.ptr;
diskList[diskListLength++].memFlag = 0;
return true;
}
@ -164,3 +210,20 @@ static char *EncodeQueryString(char *queryString) {
*s = '\0';
return encodedStr;
}
static void InsertDiskListEntry(struct diskListEntry *entry) {
if (diskListLength >= DISK_LIST_MAX_LENGTH)
return;
diskList[diskListLength++] = *entry;
}
void FreeJSON(void) {
for (int i = 0; i < MAX_PAGES; i++) {
if (json[i] != NULL) {
json_value_free(json[i]);
json[i] = NULL;
}
}
}

View File

@ -1,6 +1,7 @@
#ifndef DISKSEARCH_H
#define DISKSEARCH_H
void DoSearch(void);
void DoSearch(boolean getMore);
void FreeJSON(void);
#endif