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: case wInControl:
switch (taskRec->wmTaskData4) { switch (taskRec->wmTaskData4) {
case searchButton: case searchButton:
DoSearch(); DoSearch(false);
break;
case forIIGSRadio:
gsDisksOnly = true;
break;
case forAnyAppleIIRadio:
gsDisksOnly = false;
break; break;
case mountDiskButton: case mountDiskButton:

View File

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

View File

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

View File

@ -22,15 +22,9 @@ extern GrafPortPtr window;
/* Is the window open? */ /* Is the window open? */
extern Boolean windowOpened; extern Boolean windowOpened;
/* User preference: IIGS disks or all Apple II disks? */
extern boolean gsDisksOnly;
/* Disks list control */ /* Disks list control */
extern CtlRecHndl disksListHandle; extern CtlRecHndl disksListHandle;
/* Length of disks list */
#define DISK_LIST_LENGTH 30
struct diskListEntry { struct diskListEntry {
char *memPtr; char *memPtr;
Byte memFlag; Byte memFlag;
@ -38,14 +32,25 @@ struct diskListEntry {
char *extPtr; 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 */ /* 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. */ /* Do we want to open a window with disk contents? Counts down until ready. */
extern int wantToOpenWindow; extern int wantToOpenWindow;
/* JSON for current disk list (needs to be kept in memory while it's shown) */ /* 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 */ /* User ID of this program */
extern Word myUserID; extern Word myUserID;

View File

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

View File

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

View File

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