So because of 1), I should NOT skip psysLaunchDB during
backup/restore because I'll lose category info. And because of 2), I
SHOULD skip it to avoid restoring stale cache info... A catch-22.
Exactly. But you could restore the cache, figuring that it's still valid since you
restored
I have a sharable library that puts up its own UI.
It's usually in ROM. When an updated copy of the
shared library is loaded into RAM,
the new RAM code executes, but the UI resources are
retrieved from ROM.
How are you opening your database? If you use DmGetNextDatabaseByTypeCreator
with
The problem is that if the user causes
any events while the animation is being updated, the events are
queued, and when the animation is complete, all the queued events execute.
You can use normal event processing in games, but many games poll instead.
The HardBall example app shows how to do
I am seeking detailed information regarding
the usage of callback functions in PalmOS
programming.
What you're really asking about is callbacks that are invoked by interrupt
handlers. One example is the callback passed to SrmSetWakeupHandler. The
docs for the callback (Reference, page 1382)
I was wondering whether anyone knew of a built in ... function ...
that makes a bitmap smaller or larger...
Bitmap scaling isn't provided by Palm OS, so you'll have to implement your
own. There are many algorithms to choose from depending on the speed/quality
tradeoff you want. Here's an
I need to get the Expense.prc application from the ROM of a friend's m515.
What you are trying to do is not supported by PalmSource or Palm. Applications in ROM
are designed to run from ROM and are likely to not work properly when run from RAM.
These applications do initialization on hard
How do I resize the image on Palm?
I posted an answer to a similar question just a few hours ago!
http://www.escribe.com/computing/pcpqa/m62076.html
This is the first time I've seen this question on this forum and suddenly two people
asked it. Very strange...
-
Danny
--
For information on
Post your code if you can. Don't be shy! :)
As a general rule, we like people to post their code on this forum. But don't post the
whole thing; just pick the parts that you think are relevant. We'll ask for more if
necessary. In this case, the code that calls ExgDBRead and the ReadProc
ExgDBRead stops when it thinks it's done. It knows how many records or resources there
are, so it won't stop until it's created that many. It knows when the last record or
resource is complete when the ReadProc returns 0.
It sounds like the data in the file stream is invalid. Try using
This code returns a value of 42-43 MHz
every time, which is great except that the NR70's processor is
supposed to run at 66 Mhz...
Could be wait states on the instruction fetches. Just a guess...
-
Danny
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
Does anyone know where I can get documentation on the NotePad file format or
does anyone know the file format?
AFAIK this format has never been documented. Note that this app was belongs to Palm,
not PalmSource.
-
Danny
--
For information on using the Palm Developer Forums, or to
Hi Matt.
Do any of the Palm routines that locate records specifically skip deleted
or
archived records for you ?
The docs for DmNumRecords says that it includes deleted records and that you
should use DmNumRecordsInCategory(dbP, dmAllCategories) if you want to leave
out deleted records.
By the way, if I understand correctly, an alarm is always triggered
_after_ a system operation, like a HotSync, so that I can just pass
TimGetSeconds() as the fourth parameter to AlmSetAlarm(), right?
Yup. Alarms are disabled (deferred, really) during HotSync.
-
Danny
--
For information on
Here are some options:
1. Change Poser to generate penMoveEvents.
2. Change your app to not require dragging. (You can still allow it.)
3. Change your app to not require dragging only when Gremlins is running.
4. Change your app to use EvtGetPen once the pen goes down and change Poser to move
A picture is worth 1024 words. :)
-
Danny
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/support/forums/
I was thinking about bumping the version number of the new application
to a higher value, keeping the same name and creator ID, and using
DmGetNextDatabaseByTypeCreator() to get to the older app.
The Install conduit will overwrite the existing database in this situation.
If you don't want it
Hi Matt!
This is an excerpt from Palm OS Companion2.pdf, p16, (sdk 4.0).
...
while (!err sizeSent size) {
sizeSent += ExgSend(exgSocket,bmpP,size,err);
...
Shouldn't the call to ExgSend be
sizeSent += ExgSend(exgSocket, bmpP + sizeSent, size - sizeSent, err);
The docs for ExgSend
Hi Matt!
I have archived records...
However, I want to read these 'deleted' records on the Palm, but am not
allowed.
...
- mess with the delete bit in the attributes before and after I read the
record
Does anyone know the likelihood that we won't be able to access (i.e. set)
the
This works like a charm except Gremlins finds a chunk over-lock
condition. I cannot duplicate it manually on poser or the device.
I don't know what's causing the chunk over-locked error, but you might want
to try the new Gremlins Minimization feature of Poser.
-
Danny
--
For information on
How much of the IrDA specification is already in the Palm?
This is really more of a comm-dev-forum question.
Palm OS gives you several ways of doing IrDA:
- raw IR via the [New] Serial Manager
- IrLAP, IrLMP, and IrTTP via the IR Library
- IrOBEX via the Exchange Manager
- IrCOMM via the [New]
Unfortunately, with constructor it's more difficult because it derives the
resource ID names from the menu captions. When you translate a menu item,
you'll get a different #define and need a translation header.
As long as you don't change the resource IDs in the localized resource
files, you
It seems like a bad idea, but
what are the implications of modifying a db record that was
accessed via DmQueryRecord versus DmGetRecord?
I agree, in general. However, ISTR that some of our example code does this.
I was surprised to discover that I can actually modify
a record that was
I get this error, Records left locked in closed unprotected database.
in POSE with my app.
This indicates that you closed a database without unlocking all the record
or resources that you locked. Note that it can be resources or records,
despite the error message.
error =
Actually I am now getting the error later on with the Gremlins.
The records left locked error?
recPtr = (Char *) MemHandleLock(recHandle);
err = DmWrite(recPtr, recSize, buffer, bytesReceived);
MemHandleUnlock(recHandle);
This is a well-matched pair of lock and unlock calls. There is no
I'm planning to get a couple of devices for testing purposes. I know that
some Palms have upgradable OS's and some do not.
Only devices with flash ROM (as opposed to mask ROM) can be flashed with a
new OS. However, you can install OS updates in RAM. For example, you have to
flash to go from
But if I take the .pdb file and install it
onto the Emulator (version 3.5, Windows), all of the records' Dirty flags
get set.
I confirmed this behavior. If you install a database by dropping onto
Poser's window or via Poser's Install Application/Database menu item, the
dirty bits will be set.
In OS 5, I get an error that says:
exgmgr.c line 2581libraryref not specified
on this line in my code:
err = ExgDisconnect(s, err);
It's complaining that s.libraryRef is zero. This field is typically zeroed
by your code (via a call to MemSet) before you call ExgPut. ExgPut should
I want to construct a PRC/PDB from an image stored
in a file stream and store it on the device.
I prefer to reserve the terms prc and pdb for the flattened database
format used to represent Palm databases when they're stored on a desktop. I
used the term database for the unflattened form used
Here is a snippet of the code I had. (The comments are
what was there before you emailed me, the lines under
it are what I changed).
Your changes look good. You were calling ExgDisconnect even when ExgPut
failed. This could cause the error you were seeing if the user cancels a
Send, but you
The only valid values are 0x0001 through 0x00ff.
Also, the first bunch of unique IDs are reserved for default data; e.g.
Palm's phone number and the memos that explain how to use the device.
-
Danny
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
Err iErr = DmGetNextDatabaseByTypeCreator(true, stateInfo, 'appl',
'daaA',
false, NULL, lID);
The second to last argument can't be NULL. It's used to pass back the card
number of the resulting database.
-
Danny
--
For information on using the Palm
How can I get an application's category?
A search of the archives for launcher categories turned up one of my
posts:
http://www.escribe.com/computing/pcpqa/m58358.html
--
Danny PalmSource
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
Joe pretty much covered it. See my previous post for a quick summary on
usage of DlkSetLogEntry:
http://www.escribe.com/computing/pcpqa/m44694.html
-
Danny
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/support/forums/
I wrote:
In Palm OS 4.0 and later, you can use tallCustomTableItem.
You asked:
Do you know where I can find the PalmOs SDK 4 doc in chm file ?
I'm not sure I understand, but it looks like you found a hole in our docs.
They don't mention tallCustomTableItem. Thanks for bringing this to our
What is the reason for NOT providing a Glue function?
It's just a matter of prioritization. Every time we fix a bug in the ROM, we
could include the fix in a patch for older ROMs and/or in glue code. But if
the bug is relatively minor and easily worked around, it would be a poor use
of our
It's OK I use tallCustomTableItem and it works.
Good.
But as I look in the PalmOS 3.5 docs and I thing it could be in the 4.0
docs
but I do not have these docs
It's not documented in the latest (4.0) docs, but I'm sure that'll be fixed
soon. You should get the latest docs from our website,
For those of us that have seen very little of the Palm OS internals, what
exactly does Dm semaphore refer to?
The storage heap is protected from accidental modification. When you call a
Data Manager API that modifies the storage heap, it temporarily allows write
access to the storage heap.
I need to beam records from multiple database and was wondering
what the best way was of figuring out which database the record
needs to be entered into on the receiving side.
...
Do I just place a header on the record before I beam it or what?
It sounds like you're sending your data raw.
I want to pass a string from my application to the global find, and have
it
display the search results. Can I do this?
The Find dialog uses the selection in the active field, if any, to populate
the search string field. It trims this string if necessary. If there isn't
an active field, it
I want to send a vcard from my app to the Address app without requiring
the
user to 'accept' it...can I turn off the user prompt programmatically?
In Palm OS 3.5, setting the localMode flag to true disables the do you
wanna accept dialog. The app is still sent the sysAppLaunchCmdExgAskUser
Could anyone point me to where I can get information about Palm's built in
App Launcher?
I'm looking for layout details for the 2 icon views so I my program can
navigate and select programs much like the Sony Jog Dial or Handera can
do.
The source code for the launcher is not included in
After successfully resizing a record, is the index still the same?
Yes. However, any edit to a record may invalidate the current sort order. So
you may want to move the record once you've resized it and changed its
contents.
Another question: is there any advantage to using DmNewRecord,
I use a customDraw call back to set data in a table. This call data
display data on 2 line in the cell. But I only can select the cell on
the first line. How can I increase the select area of the cell.
In Palm OS 4.0 and later, you can use tallCustomTableItem. For details,
search the
The documentation seems to indicate that EvtEventAvail returns true if an
event is available, false otherwise. I had assumed this included nilEvent
but I'm not seeing it.
There are three event queues in Palm OS: the key queue, the pen queue, and
the main event queue. It looks like
We are trying to communicate thru IR to MCP2150 chip usinf raw IR
Comm. We have tried with 57200 bps and we are able to connect till IrLMP.
And we were able to send data. But when we tried to connect with 90600 bps
we are unable to go till IrLMP.
This question belongs on comm-dev-forum. I've
I'm developing on Mac OS X and would like to be able to
test some two way IR code using POSE.
This thread probably belongs on tools-forum or comm-dev-forum.
You're using the IR Library, so I doubt Poser's redirection will help you.
Shortcut-dot-t won't help either; it loops back at the
Bottom line: should I skip the PDI sample code in 4.0, and use 3.5 sample
code for writing out PIM objects if I want my app to work on PalmOS 3.5?
That's probably your best bet. Until you require Palm OS 4.0 as a minimum,
there isn't much point using the PDI/UDA stuff in my opinion. However,
Is there a way for me (as an Exchange Manager user) to
prompt the Local Exchange Library to skip the confirmation?
See my post from this morning:
http://www.escribe.com/computing/pcpqa/m59760.html
--
Danny PalmSource
--
For information on using the Palm Developer Forums, or to
Can I call the Global Find from my application, and pass it a string to
find
(so it will bypass the user-input step and go right to the find results)?
In case this morning's post didn't make it obvious, there is no API to go
straight to the results.
-
Danny
--
For information on using the
... my app needs to run on 3.5 and 4.0. If I'm setting the Exchange
Socket to local mode (for 3.5) via
exgSocket.localMode = 1;
That'll work fine in Palm OS 4.0 as well. If you don't specify a URL scheme,
it'll assume _beam unless localMode is 1, in which case it'll assume
_local. Since
Another comm-dev-forum question...
1. Do I need to call EvtGetEvent regularly to make IR communications
reliable?
As John Schettino wrote, yes!
2. Is there a function other than EvtGetEvent that I can use to give time
to
the IR media?
If you can get away with it, put up a progress dialog.
I know that its possible to use the Data Manager functions to change the
built in apps' databases since I have the record formats in the SDK.
Maybe
this is obvious to everyone else, but is it possible to actually call, for
example, the Datebook functions in DateDB.c like ApptChangeRecord...
I am trying to create a library(shared or static) which uses OBEX
(Exchange Manager?) to do the communication via bluetooth or IR.
I don't see any reason why you couldn't send (ExgPut) from a shared library,
but receiving is another story. The Exchange Manager uses launch codes to
communicate
You can set the version in constuctor and in the linker settings.
I manually change the one I set with the linker but can't figure
out how to change the one in the constuctor.
See this post for a description of the two different versions a Palm OS
application has:
I'm kind of surprised I didn't find that before... I searched
for not a handle on eScribe last night and didn't see this.
When I tried search for not a handle, with or without the quotes, I got
this message:
No matches were found for not a handle!
(This means that either these word(s)
See Jim Schram's post:
http://www.escribe.com/computing/pcpqa/m42099.html
and this thread:
http://www.escribe.com/computing/pcpqa/m46010.html
--
Danny PalmSource
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
how to know,
how much kb of RAM is used by An application.
An application is a resource database with type 'appl'. Use DmDatabaseSize
to find out how much storage heap any database consumes. It gives you two
numbers; one includes overhead, and one doesn't.
The launcher uses DmDatabaseSize
I have a shared library that I only want to allow
one opened session per user.
The normal usage pattern for shared libraries is to start with a SysLibFind
to see if the library is already loaded, and then only call SysLibLoad if it
isn't already loaded. You can keep track of the number of
Lemme look at your code again...
skelSRWorkDBType* x = (CatDBType*) MemHandleLock(theRecord);
...
s.description = x-Name;
...
err = BeamBytes(s, x, MemHandleSize(theRecord));
...
static Err BeamBytes(ExgSocketPtr s, void *buffer, UInt32 bytesToSend) {
...
What is CatDBType? It's pretty
do I do this:
err = BeamBytes(s, x, MemHandleSize(theRecord));
or this:
err = BeamBytes(s, x-Name, MemHandleSize(theRecord));
err = BeamBytes(s, x-Date, MemHandleSize(theRecord));
The answer is yes. :) Since you're beaming to a peer, ie. the same app
running on another device, you can
Is it possible to beam multiple databases at once, from within an app?
Mark pretty much covered it. (Thanks Mark!) I'll point you to the docs:
- Companion, volume 2, Object Exchange, Sending Data, Sending Multiple
Objects
- Companion, volume 2, Object Exchange, Sending and Receiving Databases,
I would like to use whatever list of categories a user has created in the
built-in launcher as the default list of categories for my app.
The launcher stores its category info in its own database. The format of
this database has changed twice so far, and will no doubt change again.
That's why
I just want to point out to you that this article is posted in
violation of the owner's (my corporation's) copyright.
Sorry - I didn't know. I just did a Google search and found this site. I
appreciate your willingness to make this content available via our Knowledge
Base. Thanks!
-
Danny
When i do export 0 DbName
systems answers with a could not create file
Create a subdirectory called Device in your PalmDebugger directory. That's
where it'll put the prc/pdb file.
--
Danny PalmSource
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
If card(0) storage gets low, ie less than 4K, sometimes my application
will crash during the execution of a search. The crash is deep within
the palm OS ROM code.
I haven't had a problem with this in my own apps. Is the storage heap or
dynamic heap almost full? Card zero doesn't say much;
What are you passing in as the scheme? Are you using shortcut-dot-t? What
ROM are you using?
MemHandle theRecord = DmQueryRecord(gCatDB, recordNumber);
skelSRWorkDBType* x = (CatDBType*) MemHandleLock(theRecord);
You should text if DmQueryRecord returns NULL before trying to lock the
our teeth with IR Ping, myself included. Also see
BeamBooks:
http://www.appliedthought.com/beambooks
We put the source in the public domain a while back.
Good luck!
--
Danny Epstein
PalmSource / Applied Thought
--
For information on using the Palm Developer Forums, or to unsubscribe
I've copied this excerpt from the subhunt code listed
below, but it's not working.
SubHunt uses polling. See the GameMaskKeys and GameUnmaskKeys functions in
SubHunt.c. Also look for the call to the KeyCurrentState API in
GameStateElapse.
--
Danny PalmSource
--
For information on using the
I have a console program written in Ada, and I want to port it onto palm.
Ada! No one talks about that anymore! :)
How big is it? What Ada features does it use? I hope it doesn't use tasks.
:) Does it uses packages?
By console program, I assume you mean that it's based on a command line
Hi Ted.
What is the proper way to find the storage heap on a particular card?
ie, differentiate the storage heap from the dynamic heap and the rom
heaps?
I think John Gruenenfelder is right. You said the ROM storage heap was
first. I thought it was last. I thought you could enumerate the RAM
I just did some experiments with an older version of CodeWarrior (68K). I
found that you could use:
#pragma pack(push, 1)
typedef struct {...} FooType;
#pragma pack(pop)
or:
#pragma options align=packed
typedef struct {...} FooType;
#pragma
DE That's right. The IrOBEX exchange library doesn't support the ExgConnect
DE function. You don't need it though.
MP That's odd - I could swear that the docs said that using ExgConnect is
MP _required_ when sending multiple objects. I guess you're providing the
MP additional clarification
Robert said all you need to know. I'll just add some trivia...
In the old days, there were multiple storage heaps. When you called
DmResizeRecord, it would try to resize the record's handle in the current
storage heap, first by grabbing more space where the chunk currently lives,
and if that
I'm having this odd problem with ExgConnect while running on an emulated
Palm OS 4.0 m505 device (it happens on a real 4.0 device too, a Sony
610C).
This API always returns the bad status 0x150F, Operation not supported.
That's right. The IrOBEX exchange library doesn't support the ExgConnect
You can also try entering text into the
various fields in an address record on the device, and beam the record to
a
PC or Mac laptop.
Or you can use the HostTransfer sample exchange library on Palm OS 4.0 or
later. It lets you use the Send command in Address to send a vCard to the
host PC
As it appears to me,
its value is just ignored, so I get PrgCallbackDataPtr-timedOut = 1
immediately on next PrgHandleEvent.
In my own code, I've implemented an animating icon in the Progress Manager
without using the Progress Manager's timeout feature. I used actual
throughput to drive the
I have a problem with an application that can't be installed : the hotsync
process never finish or fail and same when we try to beam the application.
It's got to be your handling of sysAppLaunchCmdSyncNotify.
The application only answer to sysAppLaunchCmdNormalLaunch.
Visually trace
My question is, when I beam a database or a selection of records that are
linked by these (external record unique ID's) what happens to them ?
Do they remain what they were, and on the recieving device I have to
ensure
that they are _still_ unique ? Does the DataManager generate NEW ID's
I'm currently using an internal UID and it's painfully slow. Rather parts
of my app are slow when I need to turn the UID into a recIndex and the
number of records to check is high.
The built-in unique ID is stored in the record header, so it's faster to
access that an app-defined ID within
The cleaning up dialog used during HotSync is for most users in the
Netherlands not that interesting.
It is a bit vague, but for many users, this is the appropriate level of
detail.
After advice of a reader I use InsertionSort instead of QuickSort to keep
my
database in order.
You should
DmRecordInfo (dbP, rec, attr, NULL, NULL);
attr |= dmRecAttrDirty;
DmSetRecordInfo (dbP, rec, attr, NULL);
This is a no-op, at least on Palm OS 4.0. (I haven't checked other
versions.) DmSetRecordInfo can't be used to modify the system use only
attributes. There is only one of these
You may also have to warn your customers not to update
your application by beaming. If I recall correctly, beaming
an application under certain conditions WILL delete all
data using the same creator signature.
Here's Gavin's explanation of the bug:
My appl uses considerable time sorting records after a hotsync.
I like to inform the user about what is happening.
I want to use an alert.
The HotSync app has its own progress dialog that shows Cleaning up while
it does the sysAppLaunchCmdSyncNotify launches. Putting up your own dialog
on top
The major suspect is NetLib, since
Palm doesn't release the source code for it. Do any of the functions in
NetLib call EvtResetAutoOffTimer()?
Yup: it calls EvtResetAutoOffTimer. I think it's trying to prevent the
device from turning off while it's waiting for data to come in over the
serial
Let me see if I can put this debate to rest...
WinScreenLock isn't useful for page flipping in games. We've discussed this
before. However, it is useful for delaying screen updates so that they
appear all at once. This is normally done with a pair of calls to
WinScreenLock. The first copies the
I wouldn't recommend attempting to validate a database's LocalID. As you
said, it's just a card-relative handle. If you attempt to access the LocalID
after the database has been deleted, the following outcomes are possible:
1. Nothing else occupies this space in memory, and your access fails
Todd, I don't think the databases of an application
will get deleted if you replace the application
with a new version during hotsync.
Correct. You might want to warn your users not to delete the old version
before installing the new one.
--
Danny PalmSource
--
For information on using the
a reset fixes the problem, so it seems to me that maybe either the Info
menu does not query the 'tver' resource every time, but rather only at a
reset, or somehow the application database does not get updated properly
after modification and it takes a reset to kick things into a known state.
1.) The stub app shows up in the list of apps. How do
you made these not visible? Is changing the type from
'appl' to something else all I need to do?
They won't show up in the Buttons panel unless they're of type 'appl'. (PQAs
may also be listed.) I was thinking that you could set
What are the conventions for choosing the file extension of a Palm
database
stored outside of the Palm? I presume that 'appl' and 'libr' databases
get
the PRC extension, and that most other database types get the PDB
extension.
The backup conduit adds an extension to the database name to
Is the source to the new notepad application available ?
That would be up to Palm (as opposed to PalmSource). I don't know what their
plans are.
--
Danny PalmSource
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/support/forums/
Does anyone knows whether is it possible to initiate retrieving
of vCards or vCalendars from the Palm?
I'm not sure what you're asking, but I have a guess... Palm OS's IrOBEX
implementation doesn't currently support GET, so you can't have some other
IrDA-capable device request a vObject from a
Alarms are only checked once a minute when the device is asleep. Perhaps
this explains the lag you're seeing.
--
Danny PalmSource
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/support/forums/
-the source for the core apps is included with the SDK (and the SDK comes
from PalmSource).
-it is also my impression that the core apps are part of the platform
(and
the platform comes from PalmSource).
If, by core, you mean the 4 PIM apps: Datebook, Address, To Do, and Memo
Pad, then
I've discovered that when you set an alarm via AlmSetAlarm() and the alarm
is triggered, the alarm code in the OS calls EvtResetAutoOffTimer().
...
I've also discovered that if you use AlmSetProcAlarm() to set a procedure
alarm, the alarm code in the OS doesn't mess with the auto-off timer.
The documentation talks about the LCD if the device was off at the time,
but
the version of the docs that I have don't say anything about the auto-off
timer.
I didn't mean to imply that this behavior was documented, just that it's
what I'd expect. There is a single API that we generally use
John Crouch wrote:
Char dst[10];
StrNCopy(dst, Longer than 10 bytes, 10);
dst[9] = 0;
As John Marshall said, check the docs. This code won't work with multi-byte
characters because the last statement might be zeroing the second byte of a
two-byte character. If you want your code to work with
I am trying to resize a chunk of database memory allocated to me while
modifying a record.
Do you mean that you're trying to resize a chunk of memory in order to
modify a record? How was the chunk allocated? If it was allocated using
DmNewRecord or the equivalent DmNewHandle, DmAttachRecord
I set the application version string programmatically, i.e. get the 'tver'
resource, modify it, etc.
Can you explain why you want to do this?
what is buffling is that under the launcher's
Info menu, the Emulator shows the desired string [that I program], but
the
real device does not, and
Speaking of the Beam dialog, is there a way to invoke it programmatically?
For that matter, what about the delete, info, and category dialogs, all in
the App menu along with Beam?
If you're thinking that you could send the launcher a custom launch code to
invoke any of these, you're out of
1 - 100 of 784 matches
Mail list logo