mirror of
https://github.com/sheumann/DiskBrowser.git
synced 2024-11-25 02:32:44 +00:00
Add support for fetching more results.
This commit is contained in:
parent
567c60040e
commit
ef301fd7fc
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
99
disksearch.c
99
disksearch.c
@ -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();
|
||||
|
||||
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);
|
||||
|
||||
if (!getMore) {
|
||||
diskList[0].memFlag = 0x80;
|
||||
for (int i = 1; i < DISK_LIST_LENGTH; i++) {
|
||||
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 */
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef DISKSEARCH_H
|
||||
#define DISKSEARCH_H
|
||||
|
||||
void DoSearch(void);
|
||||
void DoSearch(boolean getMore);
|
||||
void FreeJSON(void);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user