1795 lines
50 KiB
C
1795 lines
50 KiB
C
#include "rolodex.h"
|
|
|
|
#ifdef HAVE_XCURSES
|
|
char *XCursesProgramName="rolodex";
|
|
#endif
|
|
|
|
/*
|
|
* This is the main part of the loop.
|
|
*/
|
|
int main(void)
|
|
{
|
|
/* Declare variables. */
|
|
CDKSCREEN *cdkscreen;
|
|
CDKMENU *rolodexMenu;
|
|
CDKLABEL *rolodexTitle;
|
|
SRolodex groupList[MAXGROUPS];
|
|
WINDOW *cursesWin;
|
|
char *menulist[MAX_MENU_ITEMS][MAX_SUB_ITEMS], *title[5];
|
|
char *home, temp[256], *mesg[15];
|
|
int subMenuSize[10], menuLocations[10], selection;
|
|
int group, ret, x;
|
|
int groupCount = 0;
|
|
|
|
/* Set up CDK */
|
|
cursesWin = initscr();
|
|
cdkscreen = initCDKScreen (cursesWin);
|
|
|
|
/* Start CDK color. */
|
|
initCDKColor();
|
|
|
|
/* Create the menu lists. */
|
|
menulist[0][0] = "</U>File";menulist[1][0] = "</U>Groups";
|
|
menulist[0][1] = "</B/5>Open ";menulist[1][1] = "</B/5>New ";
|
|
menulist[0][2] = "</B/5>Save ";menulist[1][2] = "</B/5>Open ";
|
|
menulist[0][3] = "</B/5>Save As";menulist[1][3] = "</B/5>Delete";
|
|
menulist[0][4] = "</B/5>Quit ";
|
|
|
|
menulist[2][0] = "</U>Print";menulist[3][0] = "</U>Help";
|
|
menulist[2][1] = "</B/5>Print Groups";menulist[3][1] = "</B/5>About Rolodex ";
|
|
menulist[3][2] = "</B/5>Rolodex Statistics";
|
|
|
|
/* Set up the sub-menu sizes and their locations. */
|
|
subMenuSize[0] = 5;menuLocations[0] = LEFT;
|
|
subMenuSize[1] = 4;menuLocations[1] = LEFT;
|
|
subMenuSize[2] = 2;menuLocations[2] = LEFT;
|
|
subMenuSize[3] = 3;menuLocations[3] = RIGHT;
|
|
|
|
/* Create the menu. */
|
|
rolodexMenu = newCDKMenu (cdkscreen, menulist, 4,
|
|
subMenuSize, menuLocations,
|
|
TOP, A_BOLD|A_UNDERLINE, A_REVERSE);
|
|
|
|
/* Create the title. */
|
|
title[0]= "<C></U>Cdk Rolodex";
|
|
title[1]= "<C></B/24>Written by Mike Glover";
|
|
rolodexTitle = newCDKLabel (cdkscreen, CENTER, CENTER, title, 2, FALSE, FALSE);
|
|
|
|
/* Define the help key binding. */
|
|
bindCDKObject (vMENU, rolodexMenu, '?', helpCB, 0);
|
|
|
|
/* Draw the CDK screen. */
|
|
refreshCDKScreen (cdkscreen);
|
|
|
|
/* Check the value of the HOME env var. */
|
|
home = getenv ("HOME");
|
|
if (home != 0)
|
|
{
|
|
/* Make sure the $HOME/.rolodex directory exists. */
|
|
sprintf (temp, "%s/.rolodex", home);
|
|
|
|
/* Set the value of the global rolodex DBM directory. */
|
|
GDBMDir = copyChar (temp);
|
|
|
|
/* Set the value of the global RC filename. */
|
|
sprintf (temp, "%s/.rolorc", home);
|
|
GRCFile = copyChar (temp);
|
|
}
|
|
else
|
|
{
|
|
/* Set the value of the global rolodex DBM directory. */
|
|
GDBMDir = copyChar (".rolodex");
|
|
|
|
/* Set the value of the global RC filename. */
|
|
GRCFile = copyChar (".rolorc");
|
|
}
|
|
|
|
/* Make the rolodex directory. */
|
|
mkdir (GDBMDir, 0755);
|
|
|
|
/* Open the rolodex RC file. */
|
|
groupCount = readRCFile (GRCFile, groupList);
|
|
|
|
/* Check the value of groupCount. */
|
|
if (groupCount < 0)
|
|
{
|
|
/* The RC file seems to be corrupt. */
|
|
sprintf (temp, "<C></B/16>The RC file (%s) seems to be corrupt.", GRCFile);
|
|
mesg[0] = copyChar (temp);
|
|
mesg[1] = "<C></B/16>No rolodex groups were loaded.";
|
|
mesg[2] = "<C>Press any key to continue.";
|
|
popupLabel (cdkscreen, mesg, 3);
|
|
freeChar (mesg[0]);
|
|
groupCount = 0;
|
|
}
|
|
else if (groupCount == 0)
|
|
{
|
|
mesg[0] = "<C></B/24>Empty rolodex RC file. No groups loaded.";
|
|
mesg[1] = "<C>Press any key to continue.";
|
|
popupLabel (cdkscreen, mesg, 2);
|
|
}
|
|
else
|
|
{
|
|
if (groupCount == 1)
|
|
{
|
|
sprintf (temp, "<C></24>There was 1 group loaded from the RC file.");
|
|
}
|
|
else
|
|
{
|
|
sprintf (temp, "<C></24>There were %d groups loaded from the RC file.", groupCount);
|
|
}
|
|
mesg[0] = copyChar (temp);
|
|
mesg[1] = "<C>Press any key to continue.";
|
|
popupLabel (cdkscreen, mesg, 2);
|
|
freeChar (mesg[0]);
|
|
}
|
|
|
|
/* Loop until we are done. */
|
|
for (;;)
|
|
{
|
|
/* Activate the menu */
|
|
selection= activateCDKMenu (rolodexMenu, 0);
|
|
|
|
/* Check the return value of the selection. */
|
|
if (selection == 0)
|
|
{
|
|
/* Open the rolodex RC file. */
|
|
groupCount = openNewRCFile (cdkscreen, groupList, groupCount);
|
|
}
|
|
else if (selection == 1)
|
|
{
|
|
/* Write out the RC file. */
|
|
ret = writeRCFile (cdkscreen, GRCFile, groupList, groupCount);
|
|
|
|
/* Reset the saved flag if the rc file saved ok. */
|
|
if (ret != 0)
|
|
{
|
|
GGroupModified = 0;
|
|
}
|
|
}
|
|
else if (selection == 2)
|
|
{
|
|
/* Save as. */
|
|
ret = writeRCFileAs (cdkscreen, groupList, groupCount);
|
|
|
|
/* Reset the saved flag if the rc file saved ok. */
|
|
if (ret != 0)
|
|
{
|
|
GGroupModified = 0;
|
|
}
|
|
}
|
|
else if (selection == 3)
|
|
{
|
|
/* Has anything changed??? */
|
|
if (GGroupModified != 0)
|
|
{
|
|
/* Write out the RC file. */
|
|
writeRCFile (cdkscreen, GRCFile, groupList, groupCount);
|
|
}
|
|
|
|
/* Remove the CDK widget pointers. */
|
|
destroyCDKMenu (rolodexMenu);
|
|
destroyCDKLabel (rolodexTitle);
|
|
destroyCDKScreen (cdkscreen);
|
|
delwin (cursesWin);
|
|
|
|
/* Free up other pointers. */
|
|
freeChar (GCurrentGroup);
|
|
freeChar (GRCFile);
|
|
freeChar (GDBMDir);
|
|
|
|
/* Clean up the group information. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
freeChar (groupList[x].name);
|
|
freeChar (groupList[x].desc);
|
|
freeChar (groupList[x].dbm);
|
|
}
|
|
|
|
/* Shutdown CDK. */
|
|
endCDK();
|
|
|
|
/* Exit cleanly. */
|
|
exit (0);
|
|
}
|
|
else if (selection == 100)
|
|
{
|
|
/* Add a new group to the list. */
|
|
groupCount = addRolodexGroup (cdkscreen, groupList, groupCount);
|
|
}
|
|
else if (selection == 101)
|
|
{
|
|
/* If there are no groups, ask them if they want to create a new one. */
|
|
if (groupCount == 0)
|
|
{
|
|
char *buttons[] = {"<Yes>", "<No>"};
|
|
mesg[0] = "<C>There are no groups defined.";
|
|
mesg[1] = "<C>Do you want to define a new group?";
|
|
|
|
/* Add the group if they said yes. */
|
|
if (popupDialog (cdkscreen, mesg, 2, buttons, 2) == 0)
|
|
{
|
|
groupCount = addRolodexGroup (cdkscreen, groupList, groupCount);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Get the number of the group to open. */
|
|
group = pickRolodexGroup (cdkscreen, "<C></B/29>Open Rolodex Group",
|
|
groupList, groupCount);
|
|
|
|
/* Make sure a group was picked. */
|
|
if (group >= 0)
|
|
{
|
|
/* Set the global variable GCurrentGroup */
|
|
freeChar (GCurrentGroup);
|
|
GCurrentGroup = copyChar (groupList[group].name);
|
|
|
|
/* Try to open the DBM file and read the contents. */
|
|
useRolodexGroup (cdkscreen,
|
|
groupList[group].name,
|
|
groupList[group].desc,
|
|
groupList[group].dbm);
|
|
}
|
|
}
|
|
}
|
|
else if (selection == 102)
|
|
{
|
|
/* Delete the group chosen. */
|
|
groupCount = deleteRolodexGroup (cdkscreen, groupList, groupCount);
|
|
}
|
|
else if (selection == 200)
|
|
{
|
|
/* Print Phone Number Group. */
|
|
printGroupNumbers (cdkscreen, groupList, groupCount);
|
|
}
|
|
else if (selection == 300)
|
|
{
|
|
/* About Rolodex. */
|
|
aboutCdkRolodex(cdkscreen);
|
|
}
|
|
else if (selection == 301)
|
|
{
|
|
displayRolodexStats (ScreenOf(rolodexMenu), groupCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This writes out the new RC file.
|
|
*/
|
|
int writeRCFile (CDKSCREEN *screen, char *filename, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
char *mesg[5], temp[256];
|
|
time_t clck;
|
|
FILE *fd;
|
|
int x;
|
|
|
|
/* Can we open the file? */
|
|
if ((fd = fopen (filename, "w")) == 0)
|
|
{
|
|
/* Pop up a message. */
|
|
sprintf (temp, "</B/16>The file <%s> could not be opened.", filename);
|
|
mesg[0] = copyChar (temp);
|
|
#ifdef HAVE_STRERROR
|
|
sprintf (temp, "<C></B/16>%s", strerror(errno));
|
|
#else
|
|
sprintf (temp, "<C></B/16>Unknown reason.");
|
|
#endif
|
|
mesg[1] = copyChar (temp);
|
|
mesg[2] = "<C>Press any key to continue.";
|
|
|
|
popupLabel (screen, mesg, 3);
|
|
|
|
freeChar (mesg[0]);
|
|
freeChar (mesg[1]);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/* Get the current time. */
|
|
time(&clck);
|
|
|
|
/* Put some comments at the top of the header. */
|
|
fprintf (fd, "#\n");
|
|
fprintf (fd, "# This file was automatically generated on %s", ctime(&clck));
|
|
fprintf (fd, "#\n");
|
|
|
|
/* Start writing the RC file. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
fprintf (fd, "%s%c%s%c%s\n",
|
|
groupList[x].name, CONTROL('V'),
|
|
groupList[x].desc, CONTROL('V'),
|
|
groupList[x].dbm);
|
|
}
|
|
fclose (fd);
|
|
|
|
/* Pop up a message stating that it has been saved. */
|
|
if (groupCount == 1)
|
|
{
|
|
sprintf (temp, "There was 1 group saved to file");
|
|
mesg[0] = copyChar (temp);
|
|
}
|
|
else
|
|
{
|
|
sprintf (temp, "There were %d groups saved to file", groupCount);
|
|
mesg[0] = copyChar (temp);
|
|
}
|
|
|
|
sprintf (temp, "<C>%s", filename);
|
|
mesg[1] = copyChar (temp);
|
|
mesg[2] = "<C>Press any key to continue.";
|
|
|
|
popupLabel (screen, mesg, 3);
|
|
|
|
/* Clean up. */
|
|
freeChar (mesg[0]);
|
|
freeChar (mesg[1]);
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* This allows the user to pick a DBM file to open.
|
|
*/
|
|
int pickRolodexGroup (CDKSCREEN *screen, char *title, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSCROLL *roloList = 0;
|
|
int height = groupCount;
|
|
char *mesg[MAXGROUPS], temp[256];
|
|
int selection, x;
|
|
|
|
/* Determine the height of the scrolling list. */
|
|
if (groupCount > 5)
|
|
{
|
|
height = 5;
|
|
}
|
|
height += 3;
|
|
|
|
/* Copy the names of the scrolling list into an array. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
sprintf (temp, "<C></B/29>%s", groupList[x].name);
|
|
mesg[x] = copyChar (temp);
|
|
}
|
|
|
|
/* Create the scrolling list. */
|
|
roloList = newCDKScroll (screen, CENTER, CENTER, NONE,
|
|
height, 50, title, mesg, groupCount,
|
|
NONUMBERS, A_REVERSE, TRUE, FALSE);
|
|
|
|
/* Create a callback to the scrolling list. */
|
|
bindCDKObject (vSCROLL, roloList, '?', groupInfoCB, groupList);
|
|
|
|
/* Activate the scrolling list. */
|
|
selection = activateCDKScroll (roloList, 0);
|
|
|
|
/* Destroy the scrolling list. */
|
|
destroyCDKScroll (roloList);
|
|
freeCharList (mesg, groupCount);
|
|
|
|
/* Return the item selected. */
|
|
return selection;
|
|
}
|
|
|
|
/*
|
|
* This allows the user to add a rolo group to the list.
|
|
*/
|
|
int addRolodexGroup (CDKSCREEN *screen, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKENTRY *newName= 0;
|
|
CDKENTRY *newDesc= 0;
|
|
char *mesg[4], *desc, *newGroupName, temp[256];
|
|
int x;
|
|
|
|
/* Create the name widget. */
|
|
newName = newCDKEntry (screen, CENTER, 8,
|
|
"<C></B/29>New Group Name",
|
|
"</B/29> Name: ",
|
|
A_NORMAL, '_', vMIXED,
|
|
20, 2, 256, TRUE, FALSE);
|
|
|
|
|
|
/* Get the name. */
|
|
newGroupName = activateCDKEntry (newName, 0);
|
|
|
|
/* Make sure they didn't hit escape. */
|
|
if (newName->exitType == vESCAPE_HIT)
|
|
{
|
|
mesg[0] = "<C></B/16>Add Group Canceled.";
|
|
destroyCDKEntry (newName);
|
|
popupLabel (screen, mesg, 1);
|
|
return groupCount;
|
|
}
|
|
|
|
/* Make sure that group name does not already exist. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
if (strcmp (newGroupName, groupList[x].name) == 0)
|
|
{
|
|
sprintf (temp, "<C></B/16>Sorry the group (%s) already exists.", newGroupName);
|
|
mesg[0] = copyChar (temp);
|
|
popupLabel (screen, mesg, 1);
|
|
freeChar (mesg[0]);
|
|
destroyCDKEntry (newName);
|
|
return groupCount;
|
|
}
|
|
}
|
|
|
|
/* Keep the name. */
|
|
groupList[groupCount].name = copyChar (newGroupName);
|
|
|
|
/* Create the description widget. */
|
|
newDesc = newCDKEntry (screen, CENTER, 13,
|
|
"<C></B/29>Group Description",
|
|
"</B/29>Descriprion: ",
|
|
A_NORMAL, '_', vMIXED,
|
|
20, 2, 256, TRUE, FALSE);
|
|
|
|
/* Get the description. */
|
|
desc = activateCDKEntry (newDesc, 0);
|
|
|
|
/* Check if they hit escape or not. */
|
|
if (newDesc->exitType == vESCAPE_HIT)
|
|
{
|
|
groupList[groupCount].desc = copyChar ("No Description Provided.");
|
|
}
|
|
else
|
|
{
|
|
groupList[groupCount].desc = copyChar (desc);
|
|
}
|
|
|
|
/* Create the DBM filename. */
|
|
sprintf (temp, "%s/%s.phl", GDBMDir, groupList[groupCount].name);
|
|
groupList[groupCount].dbm = copyChar (temp);
|
|
|
|
/* Inrement the group count. */
|
|
groupCount++;
|
|
GGroupModified = 1;
|
|
|
|
/* Destroy the widgets. */
|
|
destroyCDKEntry (newName);
|
|
destroyCDKEntry (newDesc);
|
|
return groupCount;
|
|
}
|
|
|
|
/*
|
|
* This displays rolodex information.
|
|
*/
|
|
void displayRolodexStats (CDKSCREEN *screen, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
char *mesg[6], temp[256];
|
|
|
|
/* Create the information to display. */
|
|
mesg[0] = "<C></U>Rolodex Statistics";
|
|
sprintf (temp, "</B/5>Read Command Filename<!B!5> </U>%s<!U>", GRCFile);
|
|
mesg[1] = copyChar (temp);
|
|
sprintf (temp, "</B/5>Group Count <!B!5> </U>%d<!U>", groupCount);
|
|
mesg[2] = copyChar (temp);
|
|
|
|
/* Display the message. */
|
|
popupLabel (screen, mesg, 3);
|
|
|
|
/* Clean up. */
|
|
freeChar (mesg[1]);
|
|
freeChar (mesg[2]);
|
|
}
|
|
|
|
/*
|
|
* This function gets a new rc filename and saves the contents of the
|
|
* groups under that name.
|
|
*/
|
|
int writeRCFileAs (CDKSCREEN *screen, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKENTRY *newRCFile;
|
|
char *newFilename;
|
|
int ret;
|
|
|
|
/* Create the entry field. */
|
|
newRCFile = newCDKEntry (screen, CENTER, CENTER,
|
|
"<C></R>Save As",
|
|
"Filename: ",
|
|
A_NORMAL, '_', vMIXED,
|
|
20, 2, 256, TRUE, FALSE);
|
|
|
|
/* Add a pre-process function so no spaces are introduced. */
|
|
setCDKEntryPreProcess (newRCFile, entryPreProcessCB, 0);
|
|
|
|
/* Get the filename. */
|
|
newFilename = activateCDKEntry (newRCFile, 0);
|
|
|
|
/* Check if they hit escape or not. */
|
|
if (newRCFile->exitType == vESCAPE_HIT)
|
|
{
|
|
destroyCDKEntry (newRCFile);
|
|
return 1;
|
|
}
|
|
|
|
/* Call the function to save the RC file. */
|
|
ret = writeRCFile (screen, newFilename, groupList, groupCount);
|
|
|
|
/* Reset the saved flag if the rc file saved ok. */
|
|
if (ret != 0)
|
|
{
|
|
/* Change the default filename. */
|
|
freeChar (GRCFile);
|
|
GRCFile = copyChar (newFilename);
|
|
GGroupModified = 0;
|
|
}
|
|
|
|
/* Clean up. */
|
|
destroyCDKEntry (newRCFile);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This opens a new RC file.
|
|
*/
|
|
int openNewRCFile (CDKSCREEN *screen, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKFSELECT *fileSelector;
|
|
char *filename, *mesg[10], temp[256];
|
|
int x;
|
|
|
|
/* Get the filename. */
|
|
fileSelector = newCDKFselect (screen, CENTER, CENTER, 20, 55,
|
|
"<C>Open RC File",
|
|
"Filename: ",
|
|
A_NORMAL, '.', A_REVERSE,
|
|
"</5>", "</48>", "</N>", "</N>",
|
|
TRUE, FALSE);
|
|
|
|
/* Activate the file selector. */
|
|
filename = activateCDKFselect (fileSelector, 0);
|
|
|
|
/* Check if the file selector left early. */
|
|
if (fileSelector->exitType == vESCAPE_HIT)
|
|
{
|
|
destroyCDKFselect (fileSelector);
|
|
mesg[0] = "Open New RC File Aborted.";
|
|
popupLabel (screen, mesg, 1);
|
|
return groupCount;
|
|
}
|
|
|
|
/* Clean out the old information. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
freeChar (groupList[x].name);
|
|
freeChar (groupList[x].desc);
|
|
freeChar (groupList[x].dbm);
|
|
}
|
|
|
|
/* Open the RC file. */
|
|
groupCount = readRCFile (filename, groupList);
|
|
|
|
/* Check the return value. */
|
|
if (groupCount < 0)
|
|
{
|
|
/* This file does not appear to be a rolodex file. */
|
|
mesg[0] = "<C></B/16>The file<!B!16>";
|
|
sprintf (temp, "<C></B/16>(%s)<!B!16>", filename);
|
|
mesg[1] = copyChar (temp);
|
|
mesg[2] = "<C>does not seem to be a rolodex RC file.";
|
|
mesg[3] = "<C>Press any key to continue.";
|
|
popupLabel (screen, mesg, 4);
|
|
freeChar (mesg[1]);
|
|
groupCount = 0;
|
|
}
|
|
|
|
/* Clean up. */
|
|
destroyCDKFselect (fileSelector);
|
|
return groupCount;
|
|
}
|
|
|
|
/*
|
|
* This reads the users rc file.
|
|
*/
|
|
int readRCFile (char *filename, SRolodex *groupList)
|
|
{
|
|
/* Declare variables. */
|
|
int groupsFound= 0;
|
|
int errorsFound= 0;
|
|
char *lines[MAX_LINES];
|
|
char **items;
|
|
int linesRead, chunks, x;
|
|
|
|
/* Open the file and start reading. */
|
|
linesRead = readFile (filename, lines, MAX_LINES);
|
|
|
|
/* Check the number of lines read. */
|
|
if (linesRead == 0)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Cycle through what was given to us and save it.
|
|
*/
|
|
for (x=0; x < linesRead; x++)
|
|
{
|
|
/* Strip white space from the line. */
|
|
stripWhiteSpace (vBOTH, lines[x]);
|
|
|
|
/* Only split lines which do not start with a # */
|
|
if (strlen (lines[x]) != 0 && lines[x][0] != '#')
|
|
{
|
|
items = CDKsplitString (lines[x], CONTROL('V'));
|
|
chunks = CDKcountStrings (items);
|
|
|
|
/* Only take the ones which fit the format. */
|
|
if (chunks == 3)
|
|
{
|
|
/* Clean off the name and DB name. */
|
|
stripWhiteSpace (vBOTH, items[0]);
|
|
stripWhiteSpace (vBOTH, items[1]);
|
|
stripWhiteSpace (vBOTH, items[2]);
|
|
|
|
/* Set the group name and DB name. */
|
|
groupList[groupsFound].name = items[0];
|
|
groupList[groupsFound].desc = items[1];
|
|
groupList[groupsFound].dbm = items[2];
|
|
groupsFound++;
|
|
free(items);
|
|
}
|
|
else
|
|
{
|
|
CDKfreeStrings(items);
|
|
errorsFound++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Clean up. */
|
|
freeCharList (lines, linesRead);
|
|
|
|
/* Check the number of groups to the number of errors. */
|
|
if (errorsFound > 0 && groupsFound == 0)
|
|
{
|
|
/* This does NOT look like the rolodex RC file. */
|
|
return -1;
|
|
}
|
|
return groupsFound;
|
|
}
|
|
|
|
/*
|
|
* This function allows the user to add/delete/modify/save the
|
|
* contents of a rolodex group.
|
|
*/
|
|
void useRolodexGroup (CDKSCREEN *screen, char *groupName, char *groupDesc GCC_UNUSED, char *groupDBM)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSCROLL *nameList= 0;
|
|
CDKLABEL *helpWindow = 0;
|
|
SPhoneData phoneData;
|
|
SPhoneRecord *phoneRecord;
|
|
char *Index[MAX_ITEMS], *title[3], *mesg[3], temp[256];
|
|
int phoneCount, selection, height, x;
|
|
|
|
/* Set up the help window at the bottom of the screen. */
|
|
title[0] = "<C><#HL(30)>";
|
|
title[1] = "<C>Press </B>?<!B> to get detailed help.";
|
|
title[2] = "<C><#HL(30)>";
|
|
helpWindow= newCDKLabel (screen, CENTER, BOTTOM, title, 3, FALSE, FALSE);
|
|
drawCDKLabel (helpWindow, FALSE);
|
|
|
|
/* Open the DBM file and read in the contents of the file */
|
|
phoneCount = readPhoneDataFile (groupDBM, &phoneData);
|
|
phoneData.recordCount = phoneCount;
|
|
|
|
/* Check the number of entries returned. */
|
|
if (phoneCount == 0)
|
|
{
|
|
/*
|
|
* They tried to open an empty group, maybe they want to
|
|
* add a new entry to this number.
|
|
*/
|
|
char *buttons[] = {"<Yes>", "<No>"};
|
|
mesg[0] = "<C>There were no entries in this group.";
|
|
mesg[1] = "<C>Do you want to add a new listng?";
|
|
if (popupDialog (screen, mesg, 2, buttons, 2) == 1)
|
|
{
|
|
destroyCDKLabel (helpWindow);
|
|
return;
|
|
}
|
|
|
|
/* Get the information for a new number. */
|
|
if (addPhoneRecord (screen, &phoneData) != 0)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else if (phoneCount < 0)
|
|
{
|
|
mesg[0] = "<C>Could not open the database for this group.";
|
|
popupLabel (screen, mesg, 1);
|
|
destroyCDKLabel (helpWindow);
|
|
return;
|
|
}
|
|
|
|
/* Set up the data needed for the scrolling list. */
|
|
for (x=0; x < phoneData.recordCount; x++)
|
|
{
|
|
phoneRecord = &phoneData.record[x];
|
|
sprintf (temp, "</B/29>%s (%s)", phoneRecord->name, GLineType[phoneRecord->lineType]);
|
|
Index[x] = copyChar (temp);
|
|
}
|
|
sprintf (temp, "<C>Listing of Group </U>%s", groupName);
|
|
height = (phoneData.recordCount > 5 ? 8 : phoneData.recordCount+3);
|
|
|
|
/* Create the scrolling list. */
|
|
nameList = newCDKScroll (screen, CENTER, CENTER, RIGHT,
|
|
height, 50, temp, Index,
|
|
phoneData.recordCount,
|
|
NUMBERS, A_REVERSE, TRUE, FALSE);
|
|
|
|
/* Clean up. */
|
|
freeCharList (Index, phoneData.recordCount);
|
|
|
|
/* Create key bindings. */
|
|
bindCDKObject (vSCROLL, nameList, 'i', insertPhoneEntryCB, &phoneData);
|
|
bindCDKObject (vSCROLL, nameList, 'd', deletePhoneEntryCB, &phoneData);
|
|
bindCDKObject (vSCROLL, nameList, DELETE, deletePhoneEntryCB, &phoneData);
|
|
bindCDKObject (vSCROLL, nameList, '?', phoneEntryHelpCB, 0);
|
|
|
|
/* Let them play. */
|
|
selection = 0;
|
|
while (selection >= 0)
|
|
{
|
|
/* Get the information they want to view. */
|
|
selection = activateCDKScroll (nameList, 0);
|
|
|
|
/* Display the information. */
|
|
if (selection >= 0)
|
|
{
|
|
/* Display the information. */
|
|
displayPhoneInfo (screen, phoneData.record[selection]);
|
|
}
|
|
}
|
|
|
|
/* Save the rolodex information to file. */
|
|
if (savePhoneDataFile (groupDBM, &phoneData) == 0)
|
|
{
|
|
/* Something happened. */
|
|
mesg[0] = "<C>Could not save phone data to data file.";
|
|
mesg[1] = "<C>All changes have been lost.";
|
|
popupLabel (screen, mesg, 2);
|
|
}
|
|
|
|
/* Clean up. */
|
|
for (x=0; x < phoneData.recordCount; x++)
|
|
{
|
|
freeChar (phoneData.record[x].name);
|
|
freeChar (phoneData.record[x].phoneNumber);
|
|
freeChar (phoneData.record[x].address);
|
|
freeChar (phoneData.record[x].city);
|
|
freeChar (phoneData.record[x].province);
|
|
freeChar (phoneData.record[x].postalCode);
|
|
freeChar (phoneData.record[x].desc);
|
|
}
|
|
destroyCDKScroll (nameList);
|
|
destroyCDKLabel (helpWindow);
|
|
}
|
|
|
|
/*
|
|
* This opens a phone data file and returns the number of elements read.
|
|
*/
|
|
int readPhoneDataFile (char *dataFile, SPhoneData *phoneData)
|
|
{
|
|
/* Declare variables. */
|
|
char *lines[MAX_LINES];
|
|
char **items;
|
|
int linesRead= 0;
|
|
int chunks= 0;
|
|
int linesFound= 0;
|
|
int x;
|
|
|
|
/* Open the file and start reading. */
|
|
linesRead = readFile (dataFile, lines, MAX_LINES);
|
|
|
|
/* Check the number of lines read. */
|
|
if ((linesRead == 0) || (linesRead == -1))
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Cycle through what was given to us and save it.
|
|
*/
|
|
for (x=0; x < linesRead; x++)
|
|
{
|
|
if (lines[x][0] != '#')
|
|
{
|
|
/* Split the string. */
|
|
items = CDKsplitString (lines[x], CONTROL('V'));
|
|
chunks = CDKcountStrings (items);
|
|
|
|
/* Copy the chunks. */
|
|
if (chunks == 8)
|
|
{
|
|
phoneData->record[linesFound].name = items[0];
|
|
phoneData->record[linesFound].lineType = atoi (items[1]);
|
|
phoneData->record[linesFound].phoneNumber = items[2];
|
|
phoneData->record[linesFound].address = items[3];
|
|
phoneData->record[linesFound].city = items[4];
|
|
phoneData->record[linesFound].province = items[5];
|
|
phoneData->record[linesFound].postalCode = items[6];
|
|
phoneData->record[linesFound].desc = items[7];
|
|
freeChar (items[1]);
|
|
free (items);
|
|
linesFound++;
|
|
}
|
|
else
|
|
{
|
|
/* Bad line in the file; recover the memory. */
|
|
CDKfreeStrings(items);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Clean up. */
|
|
freeCharList (lines, linesRead);
|
|
|
|
/* Keep the record count and return. */
|
|
phoneData->recordCount = linesFound;
|
|
return linesFound;
|
|
}
|
|
|
|
/*
|
|
* This opens a phone data file and returns the number of elements read.
|
|
*/
|
|
int savePhoneDataFile (char *filename, SPhoneData *phoneData)
|
|
{
|
|
/* Declare variables. */
|
|
SPhoneRecord *phoneRecord;
|
|
time_t clck;
|
|
FILE *fd;
|
|
int x;
|
|
|
|
/* Can we open the file? */
|
|
if ((fd = fopen (filename, "w")) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* Get the current time. */
|
|
time(&clck);
|
|
|
|
/* Add the header to the file. */
|
|
fprintf (fd, "#\n");
|
|
fprintf (fd, "# This file was automatically saved on %s", ctime(&clck));
|
|
fprintf (fd, "# There should be %d phone numbers in this file.\n", phoneData->recordCount);
|
|
fprintf (fd, "#\n");
|
|
|
|
/* Cycle through the data and start writing it to the file. */
|
|
for (x=0; x < phoneData->recordCount; x++)
|
|
{
|
|
/* Get a pointer to the object. */
|
|
phoneRecord = &phoneData->record[x];
|
|
|
|
/* Check the phone type. */
|
|
if (phoneRecord->lineType == vCell || phoneRecord->lineType == vPager)
|
|
{
|
|
fprintf (fd, "%s%c%d%c%s%c-%c-%c-%c-%c%s\n",
|
|
phoneRecord->name, CONTROL('V'),
|
|
phoneRecord->lineType, CONTROL('V'),
|
|
phoneRecord->phoneNumber, CONTROL('V'),
|
|
CONTROL('V'), CONTROL('V'), CONTROL('V'), CONTROL('V'),
|
|
phoneRecord->desc);
|
|
}
|
|
else
|
|
{
|
|
fprintf (fd, "%s%c%d%c%s%c%s%c%s%c%s%c%s%c%s\n",
|
|
phoneRecord->name, CONTROL('V'),
|
|
phoneRecord->lineType, CONTROL('V'),
|
|
phoneRecord->phoneNumber, CONTROL('V'),
|
|
phoneRecord->address, CONTROL('V'),
|
|
phoneRecord->city, CONTROL('V'),
|
|
phoneRecord->province, CONTROL('V'),
|
|
phoneRecord->postalCode, CONTROL('V'),
|
|
phoneRecord->desc);
|
|
}
|
|
}
|
|
fclose (fd);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This displays the information about the phone record.
|
|
*/
|
|
void displayPhoneInfo (CDKSCREEN *screen, SPhoneRecord record)
|
|
{
|
|
/* Declare local variables. */
|
|
char *mesg[10], temp[256];
|
|
|
|
/* Check the type of line it is. */
|
|
if (record.lineType == vVoice ||
|
|
record.lineType == vData1 ||
|
|
record.lineType == vData2 ||
|
|
record.lineType == vData3 ||
|
|
record.lineType == vFAX1 ||
|
|
record.lineType == vFAX2 ||
|
|
record.lineType == vFAX3)
|
|
{
|
|
/* Create the information to display. */
|
|
sprintf (temp, "<C></U>%s Phone Record", GLineType[record.lineType]);
|
|
mesg[0] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Name <!B!29>%s", record.name);
|
|
mesg[1] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Phone Number<!B!29>%s", record.phoneNumber);
|
|
mesg[2] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Address <!B!29>%s", record.address);
|
|
mesg[3] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>City <!B!29>%s", record.city);
|
|
mesg[4] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Province <!B!29>%s", record.province);
|
|
mesg[5] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Postal Code <!B!29>%s", record.postalCode);
|
|
mesg[6] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Comment <!B!29>%s", record.desc);
|
|
mesg[7] = copyChar (temp);
|
|
|
|
/* Pop the information up on the screen. */
|
|
popupLabel (screen, mesg, 8);
|
|
|
|
/* Clean up. */
|
|
freeCharList (mesg, 8);
|
|
}
|
|
else if (record.lineType == vPager || record.lineType == vCell)
|
|
{
|
|
/* Create the information to display. */
|
|
sprintf (temp, "<C></U>%s Phone Record", GLineType[record.lineType]);
|
|
mesg[0] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Name <!B!29>%s", record.name);
|
|
mesg[1] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Phone Number<!B!29>%s", record.phoneNumber);
|
|
mesg[2] = copyChar (temp);
|
|
|
|
sprintf (temp, "</B/29>Comment <!B!29>%s", record.desc);
|
|
mesg[3] = copyChar (temp);
|
|
|
|
/* Pop the information up on the screen. */
|
|
popupLabel (screen, mesg, 4);
|
|
|
|
/* Clean up. */
|
|
freeCharList (mesg, 4);
|
|
}
|
|
else
|
|
{
|
|
mesg[0] = "<C></R>Error<!R> </U>Unknown Phone Line Type";
|
|
mesg[1] = "<C>Can not display information.";
|
|
popupLabel (screen, mesg, 2);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This function displays a little pop up window discussing this demo.
|
|
*/
|
|
void aboutCdkRolodex (CDKSCREEN *screen)
|
|
{
|
|
char *mesg[15];
|
|
|
|
mesg[0] = "<C></U>About Cdk Rolodex";
|
|
mesg[1] = " ";
|
|
mesg[2] = "</B/24>This demo was written to demonstrate the widgets";
|
|
mesg[3] = "</B/24>available with the Cdk library. Not all of the";
|
|
mesg[4] = "</B/24>Cdk widgets are used, but most of them have been.";
|
|
mesg[5] = "</B/24>I hope this little demonstration helps give you an";
|
|
mesg[6] = "</B/24>understanding of what the Cdk library offers.";
|
|
mesg[7] = " ";
|
|
mesg[8] = "<C></B/24>Have fun with it.";
|
|
mesg[9] = " ";
|
|
mesg[10] = "</B/24>ttfn,";
|
|
mesg[11] = "<C></B/24>Mike";
|
|
mesg[12] = "<C><#HL(35)>";
|
|
mesg[13] = "<R></B/24>March 1996";
|
|
|
|
popupLabel (screen, mesg, 14);
|
|
}
|
|
|
|
/*
|
|
* This deletes a rolodex group.
|
|
*/
|
|
int deleteRolodexGroup (CDKSCREEN *screen, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
char *mesg[10], *buttons[5], temp[256];
|
|
int selection, choice, x;
|
|
|
|
/* If there are no groups, pop up a message telling them. */
|
|
if (groupCount == 0)
|
|
{
|
|
mesg[0] = "<C>Error";
|
|
mesg[1] = "<C>There as no groups defined.";
|
|
popupLabel (screen, mesg, 2);
|
|
|
|
/* Return the current group count. */
|
|
return groupCount;
|
|
}
|
|
|
|
/* Get the number of the group to delete. */
|
|
selection = pickRolodexGroup (screen, "<C></U>Delete Which Rolodex Group?", groupList, groupCount);
|
|
|
|
/* Check the results. */
|
|
if (selection < 0)
|
|
{
|
|
mesg[0] = "<C> Delete Canceled ";
|
|
mesg[1] = "<C>No Group Deleted";
|
|
popupLabel (screen, mesg, 2);
|
|
return groupCount;
|
|
}
|
|
|
|
/* Let's make sure they want to delete the group. */
|
|
mesg[0] = "<C></U>Confirm Delete";
|
|
mesg[1] = "<C>Are you sure you want to delete the group";
|
|
sprintf (temp, "<C></R>%s<!R>?", groupList[selection].name);
|
|
mesg[2] = copyChar (temp);
|
|
buttons[0] = "<No>";
|
|
buttons[1] = "<Yes>";
|
|
choice = popupDialog (screen, mesg, 3, buttons, 2);
|
|
freeChar (mesg[2]);
|
|
|
|
/* Check the results of the confirmation. */
|
|
if (choice == 0)
|
|
{
|
|
mesg[0] = "<C> Delete Canceled ";
|
|
mesg[1] = "<C>No Group Deleted";
|
|
popupLabel (screen, mesg, 2);
|
|
return groupCount;
|
|
}
|
|
|
|
/* We need to delete the group file first. */
|
|
unlink (groupList[selection].dbm);
|
|
|
|
/* OK, lets delete the group. */
|
|
freeChar (groupList[selection].name);
|
|
freeChar (groupList[selection].desc);
|
|
freeChar (groupList[selection].dbm);
|
|
for (x=selection; x < groupCount-1; x++)
|
|
{
|
|
groupList[x].name = groupList[x+1].name;
|
|
groupList[x].desc = groupList[x+1].desc;
|
|
groupList[x].dbm = groupList[x+1].dbm;
|
|
}
|
|
groupCount--;
|
|
GGroupModified = 1;
|
|
|
|
/* Clean up. */
|
|
return groupCount;
|
|
}
|
|
|
|
/*
|
|
* This function gets information about a new phone number.
|
|
*/
|
|
int addPhoneRecord (CDKSCREEN *screen, SPhoneData *phoneData)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKLABEL *title;
|
|
CDKITEMLIST *itemList;
|
|
SPhoneRecord *phoneRecord;
|
|
char *titleMesg[3], *types[GLINETYPECOUNT], temp[256];
|
|
int ret, x;
|
|
|
|
/* Get the phone record pointer. */
|
|
phoneRecord = &phoneData->record[phoneData->recordCount];
|
|
|
|
/* Create a title label to display. */
|
|
titleMesg[0] = "<C></B/16>Add New Phone Record";
|
|
title = newCDKLabel (screen, CENTER, TOP, titleMesg, 1, FALSE, FALSE);
|
|
drawCDKLabel (title, FALSE);
|
|
|
|
/* Create the phone line type list. */
|
|
for (x=0; x < GLINETYPECOUNT; x++)
|
|
{
|
|
sprintf (temp, "<C></U>%s", GLineType[x]);
|
|
types[x] = copyChar (temp);
|
|
}
|
|
|
|
/* Get the phone line type. */
|
|
itemList = newCDKItemlist (screen, CENTER, CENTER,
|
|
"<C>What Type Of Line Is It?",
|
|
"Type: ",
|
|
types, GLINETYPECOUNT, 0,
|
|
TRUE, FALSE);
|
|
phoneRecord->lineType = activateCDKItemlist (itemList, 0);
|
|
destroyCDKItemlist (itemList);
|
|
|
|
/* Clean up. */
|
|
freeCharList (types, GLINETYPECOUNT);
|
|
|
|
/* Check the return code of the line type question. */
|
|
if (phoneRecord->lineType == -1)
|
|
{
|
|
phoneRecord->lineType = 0;
|
|
return 1;
|
|
}
|
|
else if (phoneRecord->lineType == vPager || phoneRecord->lineType == vCell)
|
|
{
|
|
ret = getSmallPhoneRecord (screen, phoneRecord);
|
|
}
|
|
else
|
|
{
|
|
ret = getLargePhoneRecord (screen, phoneRecord);
|
|
}
|
|
|
|
/* Check the return value from the getXXXPhoneRecord function.*/
|
|
if (ret == 0)
|
|
{
|
|
phoneData->recordCount++;
|
|
}
|
|
|
|
/* Clean up. */
|
|
destroyCDKLabel (title);
|
|
|
|
/* Return the new phone list count. */
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* This gets a phone record with all of the details.
|
|
*/
|
|
int getLargePhoneRecord (CDKSCREEN *screen, SPhoneRecord *phoneRecord)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKENTRY *nameEntry, *addressEntry, *cityEntry;
|
|
CDKENTRY *provEntry, *postalEntry, *descEntry;
|
|
CDKTEMPLATE *phoneTemplate;
|
|
char *buttons[5], *mesg[15];
|
|
int ret;
|
|
|
|
/* Define the widgets. */
|
|
nameEntry = newCDKEntry (screen, LEFT, 5,
|
|
0, "</B/5>Name: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 20, 2, 256,
|
|
TRUE, FALSE);
|
|
addressEntry = newCDKEntry (screen, RIGHT, 5,
|
|
0, "</B/5>Address: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 40, 2, 256,
|
|
TRUE, FALSE);
|
|
cityEntry = newCDKEntry (screen, LEFT, 8,
|
|
0, "</B/5>City: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 20, 2, 256,
|
|
TRUE, FALSE);
|
|
provEntry = newCDKEntry (screen, 29, 8,
|
|
0, "</B/5>Province: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 15, 2, 256,
|
|
TRUE, FALSE);
|
|
postalEntry = newCDKEntry (screen, RIGHT, 8,
|
|
0, "</B/5>Postal Code: ",
|
|
A_NORMAL,
|
|
'_', vUMIXED, 8, 2, 256,
|
|
TRUE, FALSE);
|
|
phoneTemplate = newCDKTemplate (screen, LEFT, 11,
|
|
0,
|
|
"</B/5>Number: ",
|
|
"(###) ###-####",
|
|
"(___) ___-____",
|
|
TRUE, FALSE);
|
|
descEntry = newCDKEntry (screen, RIGHT, 11,
|
|
0,
|
|
"</B/5>Description: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 20, 2, 256,
|
|
TRUE, FALSE);
|
|
|
|
/* Get the phone information. */
|
|
for (;;)
|
|
{
|
|
/* Draw the widgets on the screen. */
|
|
drawCDKEntry (nameEntry, ObjOf(nameEntry)->box);
|
|
drawCDKEntry (addressEntry, ObjOf(addressEntry)->box);
|
|
drawCDKEntry (cityEntry, ObjOf(cityEntry)->box);
|
|
drawCDKEntry (provEntry, ObjOf(provEntry)->box);
|
|
drawCDKEntry (postalEntry, ObjOf(postalEntry)->box);
|
|
drawCDKTemplate (phoneTemplate, ObjOf(phoneTemplate)->box);
|
|
drawCDKEntry (descEntry, ObjOf(descEntry)->box);
|
|
|
|
/* Activate the entries to get the information. */
|
|
phoneRecord->name = copyChar (activateCDKEntry (nameEntry, 0));
|
|
phoneRecord->address = copyChar (activateCDKEntry (addressEntry, 0));
|
|
phoneRecord->city = copyChar (activateCDKEntry (cityEntry, 0));
|
|
phoneRecord->province = copyChar (activateCDKEntry (provEntry, 0));
|
|
phoneRecord->postalCode = copyChar (activateCDKEntry (postalEntry, 0));
|
|
activateCDKTemplate (phoneTemplate, 0);
|
|
phoneRecord->phoneNumber = mixCDKTemplate (phoneTemplate);
|
|
phoneRecord->desc = copyChar (activateCDKEntry (descEntry, 0));
|
|
|
|
/* Determine if the user wants to submit the info. */
|
|
mesg[0] = "<C></U>Confirm New Phone Entry";
|
|
mesg[1] = "<C>Do you want to add this phone number?";
|
|
buttons[0] = "</B/24><Add Phone Number>";
|
|
buttons[1] = "</B/16><Cancel>";
|
|
buttons[2] = "</B/32><Modify Information>";
|
|
ret = popupDialog (screen, mesg, 2, buttons, 3);
|
|
|
|
/* Check the response of the popup dialog box. */
|
|
if (ret == 0)
|
|
{
|
|
/* The user wants to submit the information. */
|
|
destroyCDKEntry (nameEntry);
|
|
destroyCDKEntry (addressEntry);
|
|
destroyCDKEntry (cityEntry);
|
|
destroyCDKEntry (provEntry);
|
|
destroyCDKEntry (postalEntry);
|
|
destroyCDKEntry (descEntry);
|
|
destroyCDKTemplate (phoneTemplate);
|
|
return ret;
|
|
}
|
|
else if (ret == 1)
|
|
{
|
|
/* The user does not want to submit the information. */
|
|
freeChar (phoneRecord->name);
|
|
freeChar (phoneRecord->address);
|
|
freeChar (phoneRecord->city);
|
|
freeChar (phoneRecord->province);
|
|
freeChar (phoneRecord->postalCode);
|
|
freeChar (phoneRecord->phoneNumber);
|
|
freeChar (phoneRecord->desc);
|
|
destroyCDKEntry (nameEntry);
|
|
destroyCDKEntry (addressEntry);
|
|
destroyCDKEntry (cityEntry);
|
|
destroyCDKEntry (provEntry);
|
|
destroyCDKEntry (postalEntry);
|
|
destroyCDKEntry (descEntry);
|
|
destroyCDKTemplate (phoneTemplate);
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
/* The user wants to edit the information again. */
|
|
freeChar (phoneRecord->name);
|
|
freeChar (phoneRecord->address);
|
|
freeChar (phoneRecord->city);
|
|
freeChar (phoneRecord->province);
|
|
freeChar (phoneRecord->postalCode);
|
|
freeChar (phoneRecord->phoneNumber);
|
|
freeChar (phoneRecord->desc);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This gets a small phone record.
|
|
*/
|
|
int getSmallPhoneRecord (CDKSCREEN *screen, SPhoneRecord *phoneRecord)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKENTRY *nameEntry, *descEntry;
|
|
CDKTEMPLATE *phoneTemplate;
|
|
char *buttons[5], *mesg[15];
|
|
int ret;
|
|
|
|
/* Define the widgets. */
|
|
nameEntry = newCDKEntry (screen, CENTER, 8,
|
|
0, "</B/5>Name: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 20, 2, 256,
|
|
TRUE, FALSE);
|
|
phoneTemplate = newCDKTemplate (screen, CENTER, 11,
|
|
0, "</B/5>Number: ",
|
|
"(###) ###-####",
|
|
"(___) ___-____",
|
|
TRUE, FALSE);
|
|
descEntry = newCDKEntry (screen, CENTER, 14,
|
|
0, "</B/5>Description: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 20, 2, 256,
|
|
TRUE, FALSE);
|
|
|
|
/* Get the phone information. */
|
|
for (;;)
|
|
{
|
|
/* Draw the widgets on the screen. */
|
|
drawCDKEntry (nameEntry, ObjOf(nameEntry)->box);
|
|
drawCDKTemplate (phoneTemplate, ObjOf(phoneTemplate)->box);
|
|
drawCDKEntry (descEntry, ObjOf(descEntry)->box);
|
|
|
|
/* Activate the entries to get the information. */
|
|
phoneRecord->name = copyChar (activateCDKEntry (nameEntry, 0));
|
|
activateCDKTemplate (phoneTemplate, 0);
|
|
phoneRecord->phoneNumber = mixCDKTemplate (phoneTemplate);
|
|
phoneRecord->desc = copyChar (activateCDKEntry (descEntry, 0));
|
|
phoneRecord->address = copyChar ("-");
|
|
phoneRecord->city = copyChar ("-");
|
|
phoneRecord->province = copyChar ("-");
|
|
phoneRecord->postalCode = copyChar ("-");
|
|
|
|
/* Determine if the user wants to submit the info. */
|
|
mesg[0] = "<C></B/5>Confirm New Phone Entry";
|
|
mesg[1] = "<C>Do you want to add this phone number?";
|
|
buttons[0] = "</B/24><Add Phone Number>";
|
|
buttons[1] = "</B/16><Cancel>";
|
|
buttons[2] = "</B/8><Modify Information>";
|
|
ret = popupDialog (screen, mesg, 2, buttons, 3);
|
|
|
|
/* Check the response of the popup dialog box. */
|
|
if (ret == 0)
|
|
{
|
|
/* The user wants to submit the information. */
|
|
destroyCDKEntry (nameEntry);
|
|
destroyCDKEntry (descEntry);
|
|
destroyCDKTemplate (phoneTemplate);
|
|
return ret;
|
|
}
|
|
else if (ret == 1)
|
|
{
|
|
/* The user does not want to submit the information. */
|
|
freeChar (phoneRecord->name);
|
|
freeChar (phoneRecord->phoneNumber);
|
|
freeChar (phoneRecord->desc);
|
|
freeChar (phoneRecord->address);
|
|
freeChar (phoneRecord->city);
|
|
freeChar (phoneRecord->province);
|
|
freeChar (phoneRecord->postalCode);
|
|
destroyCDKEntry (nameEntry);
|
|
destroyCDKEntry (descEntry);
|
|
destroyCDKTemplate (phoneTemplate);
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
/* The user wants to edit the information again. */
|
|
freeChar (phoneRecord->name);
|
|
freeChar (phoneRecord->phoneNumber);
|
|
freeChar (phoneRecord->desc);
|
|
freeChar (phoneRecord->address);
|
|
freeChar (phoneRecord->city);
|
|
freeChar (phoneRecord->province);
|
|
freeChar (phoneRecord->postalCode);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This prints a groups phone numbers.
|
|
*/
|
|
void printGroupNumbers (CDKSCREEN *screen, SRolodex *groupList, int groupCount)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSELECTION *selectionList;
|
|
CDKENTRY *entry;
|
|
CDKLABEL *title;
|
|
char *itemList[MAX_ITEMS], *mesg[10], temp[256];
|
|
char *choices[] = {"Print to Printer ", "Print to File", "Don't Print"};
|
|
char *filename = 0;
|
|
char *printer = 0;
|
|
char *defaultPrinter = 0;
|
|
int height = groupCount;
|
|
int x;
|
|
|
|
/* Create the group list. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
itemList[x] = copyChar (groupList[x].name);
|
|
}
|
|
|
|
/* Set the height of the selection list. */
|
|
if (groupCount > 5)
|
|
{
|
|
height = 5;
|
|
}
|
|
height += 3;
|
|
|
|
/* Create the selection list. */
|
|
selectionList = newCDKSelection (screen, CENTER, CENTER, RIGHT,
|
|
height, 40,
|
|
"<C></U>Select Which Groups To Print",
|
|
itemList, groupCount,
|
|
choices, 3,
|
|
A_REVERSE, TRUE, FALSE);
|
|
|
|
/* Activate the selection list. */
|
|
if (activateCDKSelection (selectionList, 0) == -1)
|
|
{
|
|
/* Tell the user they exited early. */
|
|
destroyCDKSelection (selectionList);
|
|
mesg[0] = "<C>Print Canceled.";
|
|
popupLabel (screen, mesg, 1);
|
|
|
|
/* Clean up. */
|
|
freeCharList (itemList, groupCount);
|
|
return;
|
|
}
|
|
eraseCDKSelection (selectionList);
|
|
|
|
/* Determine which groups we want to print. */
|
|
for (x=0; x < groupCount; x++)
|
|
{
|
|
if (selectionList->selections[x] == 0)
|
|
{
|
|
/* Create a title. */
|
|
sprintf (temp, "<C></R>Printing Group [%s] to Printer", groupList[x].name);
|
|
mesg[0] = copyChar (temp);
|
|
title = newCDKLabel (screen, CENTER, TOP, mesg, 1, FALSE, FALSE);
|
|
drawCDKLabel (title, FALSE);
|
|
freeChar (mesg[0]);
|
|
|
|
/* Get the printer name to print to. */
|
|
entry = newCDKEntry (screen, CENTER, 8,
|
|
0, "</R>Printer Name: ",
|
|
A_NORMAL,
|
|
'_', vMIXED, 20, 2, 256, TRUE, FALSE);
|
|
|
|
/* Set the printer name to the default printer. */
|
|
defaultPrinter = getenv("PRINTER");
|
|
setCDKEntry (entry, defaultPrinter, 2, 256, TRUE);
|
|
printer = copyChar (activateCDKEntry (entry, 0));
|
|
destroyCDKEntry (entry);
|
|
|
|
/* Print the group. */
|
|
if (printGroup (groupList[x], "/tmp/rolodex.tmp", printer) == 0)
|
|
{
|
|
/* The group could not be printed. */
|
|
sprintf (temp, "<C>Sorry the group '%s' could not be printed.", groupList[x].name);
|
|
mesg[0] = copyChar (temp);
|
|
popupLabel (screen, mesg, 1);
|
|
freeChar (mesg[0]);
|
|
}
|
|
|
|
/* Clean up. */
|
|
destroyCDKLabel (title);
|
|
freeChar (printer);
|
|
unlink ("/tmp/rolodex.tmp");
|
|
}
|
|
else if (selectionList->selections[x] == 1)
|
|
{
|
|
/* Create a title. */
|
|
sprintf (temp, "<C></R>Printing Group [%s] to File", groupList[x].name);
|
|
mesg[0] = copyChar (temp);
|
|
title = newCDKLabel (screen, CENTER, TOP, mesg, 1, FALSE, FALSE);
|
|
drawCDKLabel (title, FALSE);
|
|
freeChar (mesg[0]);
|
|
|
|
/* Get the filename to print to. */
|
|
entry = newCDKEntry (screen, CENTER, 8,
|
|
0, "</R>Filename: ",
|
|
A_NORMAL, '_', vMIXED,
|
|
20, 2, 256, TRUE, FALSE);
|
|
filename = copyChar (activateCDKEntry (entry, 0));
|
|
destroyCDKEntry (entry);
|
|
|
|
/* Print the group. */
|
|
if (printGroup (groupList[x], filename, printer) == 0)
|
|
{
|
|
/* The group could not be printed. */
|
|
sprintf (temp, "<C>Sorry the group '%s' could not be printed.", groupList[x].name);
|
|
mesg[0] = copyChar (temp);
|
|
popupLabel (screen, mesg, 1);
|
|
freeChar (mesg[0]);
|
|
}
|
|
|
|
/* Clean up. */
|
|
destroyCDKLabel (title);
|
|
freeChar (filename);
|
|
}
|
|
}
|
|
|
|
/* Clean up. */
|
|
destroyCDKSelection (selectionList);
|
|
freeCharList (itemList, groupCount);
|
|
}
|
|
|
|
/*
|
|
* This actually prints the phone record.
|
|
*/
|
|
int printGroup (SRolodex groupRecord, char *filename, char *printer)
|
|
{
|
|
/* Declare local variables. */
|
|
uid_t uid = getuid();
|
|
char tempFilename[256], command[256];
|
|
SPhoneData phoneData;
|
|
SPhoneRecord *phoneRecord;
|
|
int phoneCount, x;
|
|
FILE *fd;
|
|
|
|
/* Read the data file. */
|
|
phoneCount = readPhoneDataFile (groupRecord.dbm, &phoneData);
|
|
|
|
/* Create the temporary filename. */
|
|
if (filename != 0)
|
|
{
|
|
sprintf (tempFilename, "%s", filename);
|
|
}
|
|
else
|
|
{
|
|
sprintf (tempFilename, "/tmp/rolodex.%d", (int)uid);
|
|
}
|
|
|
|
/* Open the file. */
|
|
if ((fd = fopen (tempFilename, "a+")) == 0)
|
|
{
|
|
/* Clean up. */
|
|
for (x=0; x < phoneCount; x++)
|
|
{
|
|
freeChar (phoneData.record[x].name);
|
|
freeChar (phoneData.record[x].phoneNumber);
|
|
freeChar (phoneData.record[x].address);
|
|
freeChar (phoneData.record[x].city);
|
|
freeChar (phoneData.record[x].province);
|
|
freeChar (phoneData.record[x].postalCode);
|
|
freeChar (phoneData.record[x].desc);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Start writing the group information to the temp file. */
|
|
fprintf (fd, "Group Name: %40s\n", groupRecord.name);
|
|
fprintf (fd, "==============================================================================\n");
|
|
for (x=0; x < phoneCount; x++)
|
|
{
|
|
phoneRecord = &phoneData.record[x];
|
|
fprintf (fd, "Name : %s\n", phoneRecord->name);
|
|
fprintf (fd, "Phone Number: %s (%s)\n", phoneRecord->phoneNumber, GLineType[phoneRecord->lineType]);
|
|
if (phoneRecord->lineType != vPager && phoneRecord->lineType != vCell)
|
|
{
|
|
fprintf (fd, "Address : %-20s, %-20s\n", phoneRecord->address, phoneRecord->city);
|
|
fprintf (fd, " : %-10s, %-10s\n", phoneRecord->province, phoneRecord->postalCode);
|
|
}
|
|
fprintf (fd, "Description : %-30s\n", phoneRecord->desc);
|
|
fprintf (fd, "------------------------------------------------------------------------------\n");
|
|
}
|
|
|
|
/* Determine if the information is going to a file or printer. */
|
|
if (printer != 0)
|
|
{
|
|
/* Print the file to the given printer. */
|
|
sprintf (command, "lpr -P%s %s", printer, tempFilename);
|
|
system (command);
|
|
|
|
/* We have to unlkink the temp file. */
|
|
unlink (tempFilename);
|
|
}
|
|
|
|
/* Clean up some memory. */
|
|
for (x=0; x < phoneCount; x++)
|
|
{
|
|
freeChar (phoneData.record[x].name);
|
|
freeChar (phoneData.record[x].phoneNumber);
|
|
freeChar (phoneData.record[x].address);
|
|
freeChar (phoneData.record[x].city);
|
|
freeChar (phoneData.record[x].province);
|
|
freeChar (phoneData.record[x].postalCode);
|
|
freeChar (phoneData.record[x].desc);
|
|
}
|
|
|
|
/* Close the filename. */
|
|
fclose (fd);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
****************************************************************
|
|
* Start of callback functions.
|
|
****************************************************************
|
|
*/
|
|
int entryPreProcessCB (EObjectType cdkType GCC_UNUSED, void *object GCC_UNUSED, void *clientData GCC_UNUSED, chtype input)
|
|
{
|
|
if (input == ' ')
|
|
{
|
|
Beep();
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This allows the user to insert a new phone entry into the database.
|
|
*/
|
|
void insertPhoneEntryCB (EObjectType cdkType GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSCROLL *scrollp= (CDKSCROLL *)object;
|
|
SPhoneData *phoneData= (SPhoneData *)clientData;
|
|
SPhoneRecord *phoneRecord= &phoneData->record[phoneData->recordCount];
|
|
char temp[256];
|
|
|
|
/* Make the scrolling list disappear. */
|
|
eraseCDKScroll (scrollp);
|
|
|
|
/* Call the function which gets phone record information. */
|
|
if (addPhoneRecord (ScreenOf(scrollp), phoneData) == 0)
|
|
{
|
|
sprintf (temp, "%s (%s)", phoneRecord->name, GLineType[phoneRecord->lineType]);
|
|
addCDKScrollItem (scrollp, temp);
|
|
}
|
|
|
|
/* Redraw the scrolling list. */
|
|
drawCDKScroll (scrollp, ObjOf(scrollp)->box);
|
|
}
|
|
|
|
/*
|
|
* This allows the user to delete a phone entry from the database.
|
|
*/
|
|
void deletePhoneEntryCB (EObjectType cdkType GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSCROLL *scrollp = (CDKSCROLL *)object;
|
|
SPhoneData *phoneData = (SPhoneData *)clientData;
|
|
char *mesg[3], temp[256], *hold;
|
|
char *buttons[] = {"</B/16><No>", "</B/24><Yes>"};
|
|
int position = scrollp->currentItem;
|
|
int x;
|
|
|
|
/* Make the scrolling list disappear. */
|
|
eraseCDKScroll (scrollp);
|
|
|
|
/* Check the number of entries left in the list. */
|
|
if (scrollp->listSize == 0)
|
|
{
|
|
mesg[0] = "There are no more numbers to delete.";
|
|
popupLabel (ScreenOf(scrollp), mesg, 1);
|
|
return;
|
|
}
|
|
|
|
/* Ask the user if they really want to delete the listing. */
|
|
mesg[0] = "<C>Do you really want to delete the phone entry";
|
|
hold = chtype2Char (scrollp->item[scrollp->currentItem]);
|
|
sprintf (temp, "<C></B/16>%s", hold);
|
|
freeChar (hold);
|
|
mesg[1] = copyChar (temp);
|
|
if (popupDialog (ScreenOf(scrollp), mesg, 2, buttons, 2) == 1)
|
|
{
|
|
/* Remove the item from the phone data record. */
|
|
for (x=position; x < phoneData->recordCount-1; x++)
|
|
{
|
|
phoneData->record[x].name = phoneData->record[x+1].name;
|
|
phoneData->record[x].lineType = phoneData->record[x+1].lineType;
|
|
phoneData->record[x].phoneNumber = phoneData->record[x+1].phoneNumber;
|
|
phoneData->record[x].address = phoneData->record[x+1].address;
|
|
phoneData->record[x].city = phoneData->record[x+1].city;
|
|
phoneData->record[x].province = phoneData->record[x+1].province;
|
|
phoneData->record[x].postalCode = phoneData->record[x+1].postalCode;
|
|
phoneData->record[x].desc = phoneData->record[x+1].desc;
|
|
}
|
|
phoneData->recordCount--;
|
|
|
|
/* Nuke the entry. */
|
|
deleteCDKScrollItem (scrollp, position);
|
|
}
|
|
|
|
/* Clean up. */
|
|
freeChar (mesg[1]);
|
|
}
|
|
|
|
/*
|
|
* This function provices help for the phone list editor.
|
|
*/
|
|
void phoneEntryHelpCB (EObjectType cdkType GCC_UNUSED, void *object, void *clientData GCC_UNUSED, chtype key GCC_UNUSED)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSCROLL *scrollp = (CDKSCROLL *)object;
|
|
char *mesg[10], temp[100];
|
|
|
|
/* Create the help title. */
|
|
mesg[0] = "<C></R>Rolodex Phone Editor";
|
|
mesg[1] = "<B=i > Inserts a new phone entry.";
|
|
mesg[2] = "<B=d > Deletes the currently selected phone entry.";
|
|
mesg[3] = "<B=Escape> Exits the scrolling list.";
|
|
mesg[4] = "<B=? > Pops up this help window.";
|
|
|
|
/* Pop up the message. */
|
|
popupLabel (ScreenOf(scrollp), mesg, 5);
|
|
}
|
|
|
|
/*
|
|
* This is a callback to the menu widget. It allows the user to
|
|
* ask for help about any sub-menu item.
|
|
*/
|
|
void helpCB (EObjectType cdkType GCC_UNUSED, void *object, void *clientData GCC_UNUSED, chtype key GCC_UNUSED)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKMENU *menu= (CDKMENU *)object;
|
|
int menuList= menu->currentTitle;
|
|
int submenuList= menu->currentSubtitle;
|
|
int selection= ((menuList * 100) + submenuList);
|
|
char *mesg[20], *name, temp[100];
|
|
|
|
/* Create the help title. */
|
|
name = chtype2Char (menu->sublist[menuList][submenuList]);
|
|
stripWhiteSpace (vBOTH, name);
|
|
sprintf (temp, "<C></R>Help<!R> </U>%s<!U>", name);
|
|
mesg[0] = copyChar (temp);
|
|
freeChar (name);
|
|
|
|
/* Set the default value for the message. */
|
|
mesg[1] = "<C>No help defined for this menu.";
|
|
|
|
/* Given the current menu item, create a message. */
|
|
if (selection == 0)
|
|
{
|
|
mesg[1] = "<C>This reads a new rolodex RC file.";
|
|
}
|
|
else if (selection == 1)
|
|
{
|
|
mesg[1] = "<C>This saves the current group information in the default RC file.";
|
|
}
|
|
else if (selection == 2)
|
|
{
|
|
mesg[1] = "<C>This saves the current group information in a new RC file.";
|
|
}
|
|
else if (selection == 3)
|
|
{
|
|
mesg[1] = "<C>This exits this program.";
|
|
}
|
|
else if (selection == 100)
|
|
{
|
|
mesg[1] = "<C>This creates a new rolodex group.";
|
|
}
|
|
else if (selection == 101)
|
|
{
|
|
mesg[1] = "<C>This opens a rolodex group.";
|
|
}
|
|
else if (selection == 102)
|
|
{
|
|
mesg[1] = "<C>This deletes a rolodex group.";
|
|
}
|
|
else if (selection == 200)
|
|
{
|
|
mesg[1] = "<C>This prints out selected groups phone numbers.";
|
|
}
|
|
else if (selection == 300)
|
|
{
|
|
mesg[1] = "<C>This gives a little history on this program.";
|
|
}
|
|
else if (selection == 301)
|
|
{
|
|
mesg[1] = "<C>This provides information about the rolodex.";
|
|
}
|
|
|
|
/* Pop up the message. */
|
|
popupLabel (ScreenOf(menu), mesg, 2);
|
|
|
|
/* Clean up. */
|
|
freeChar (mesg[0]);
|
|
}
|
|
|
|
/*
|
|
* This is a callback to the group list scrolling list.
|
|
*/
|
|
void groupInfoCB (EObjectType cdkType GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED)
|
|
{
|
|
/* Declare local variables. */
|
|
CDKSCROLL *scrollp= (CDKSCROLL *)object;
|
|
SRolodex *groupList= (SRolodex *)clientData;
|
|
int selection= scrollp->currentItem;
|
|
char *mesg[5], temp[100];
|
|
|
|
/* Create the message to be displayed. */
|
|
mesg[0] = "<C></U>Detailed Group Information.";
|
|
|
|
sprintf (temp, "</R>Group Name <!R> %s", groupList[selection].name);
|
|
mesg[1] = copyChar (temp);
|
|
|
|
sprintf (temp, "</R>Group Description <!R> %s", groupList[selection].desc);
|
|
mesg[2] = copyChar (temp);
|
|
|
|
sprintf (temp, "</R>Group Database File<!R> %s", groupList[selection].dbm);
|
|
mesg[3] = copyChar (temp);
|
|
|
|
/* Display the message. */
|
|
popupLabel (ScreenOf(scrollp), mesg, 4);
|
|
|
|
/* Clean up. */
|
|
freeChar (mesg[1]);
|
|
freeChar (mesg[2]);
|
|
freeChar (mesg[3]);
|
|
}
|