Revision 63

Date:
2007/05/20 20:16:46
Author:
gdshaw@RISCPKG.ORG
Revision Log:
Implemented automatic refresh of filer windows (by watching OS_UpCall 3).
Files:

Legend:

 
Added
 
Removed
 
Modified
  • trunk/filer/_pathname_table.s

     
    1 ; This file is part of the free Filer module for RISC OS.
    2 ; Copyright � 2007 Graham Shaw.
    3 ; Redistribution and modification are permitted under the terms of the
    4 ; GNU General Public License (version 2 or any later version).
    5
    6 ; The following offsets must match the layout of a pathname_table.
    7 table_size EQU 0
    8 table_capacity EQU 4
    9 table_index EQU 8
    10 table_nodes EQU 12
    11 table_tail EQU 16
    12 table_pollword EQU 20
    13 table_buffer EQU 24
    14
    15 ; The following offsets must match the layout of a pathname_table::node.
    16 node_next EQU 0
    17 node_refresh EQU 4
    18 node_window EQU 8
    19 node_index EQU 12
    20
    21 END
  • trunk/filer/filer_application.cc

     
    49 49 if (!handled) application::handle_key_pressed(block);
    50 50 }
    51 51
    52 void filer_application::handle_pollword_non_zero(int* pollword)
    53 {
    54 *pollword=0;
    55 pathnames.refresh();
    56 }
    57
    52 58 void filer_application::handle_user_message(wimp_event_no event,
    53 59 wimp_message& message)
    54 60 {
     
    136 142 _rename_index=directory::npos;
    137 143 }
    138 144 }
    145
    146 pathname_table::node* filer_application::register_pathname(filer_window& w)
    147 {
    148 return pathnames.insert(&w);
    149 }
    150
    151 void filer_application::deregister_pathname(pathname_table::node* n)
    152 {
    153 pathnames.erase(n);
    154 }
  • trunk/filer/filer_application.h

     
    11 11 #include "application.h"
    12 12 #include "auto_pos.h"
    13 13 #include "directory.h"
    14 #include "pathname_table.h"
    14 15
    15 16 class filer_window;
    16 17
     
    43 44 filer_application();
    44 45
    45 46 virtual void handle_key_pressed(wimp_key& block);
    47 virtual void handle_pollword_non_zero(int* pollword);
    46 48 virtual void handle_user_message(wimp_event_no event,
    47 49 wimp_message& message);
    48 50 virtual void deregister_window(window& w);
     
    65 67
    66 68 /** Cancel rename operation if one is in progress. */
    67 69 void cancel_rename();
    70
    71 /** Register pathname of filer window.
    72 * @param w the window
    73 * @return a pointer to the pathname table node
    74 */
    75 pathname_table::node* register_pathname(filer_window& w);
    76
    77 /** Deregister pathname of filer window.
    78 * @param n a pointer to the pathname table node
    79 */
    80 void deregister_pathname(pathname_table::node* n);
    68 81 };
    69 82
    70 83 #endif
  • trunk/filer/filer_window.cc

     
    111 111 open.yscroll=wstate.yscroll;
    112 112 open.next=wimp_TOP;
    113 113 open_window(open);
    114
    115 // Register this window in the pathnames table.
    116 if (app) _pathname_node=app->register_pathname(*this);
    114 117 }
    115 118
    116 119 filer_window::~filer_window()
    117 120 {
    121 // Deregister this window from the pathnames table.
    122 if (filer_application* app=
    123 dynamic_cast<filer_application*>(parent_application()))
    124 {
    125 app->deregister_pathname(_pathname_node);
    126 }
    127
    118 128 // Delete pathname buffer.
    119 129 delete[] _pathname;
    120 130 }
  • trunk/filer/filer_window.h

     
    7 7 #define FILER_FILER_WINDOW
    8 8
    9 9 #include "directory.h"
    10 #include "pathname_table.h"
    10 11 #include "auto_pos.h"
    11 12 #include "window.h"
    12 13 #include "filer_options.h"
     
    48 49 /** The position at which a filer window for a subdirectory will be
    49 50 * opened. */
    50 51 auto_pos _auto_pos;
    52
    53 /** The node within the pathname table that corresponds to this filer
    54 * window (and which is needed to deregister the pathname when this
    55 * window is destroyed). */
    56 pathname_table::node* _pathname_node;
    51 57 public:
    52 58 /** Construct filer window.
    53 59 * @param app the application to which this filer window belongs
  • trunk/filer/main.cc

     
    15 15
    16 16 filer_application* app=0;
    17 17
    18 int pollword=0;
    19
    20 pathname_table pathnames(&pollword);
    21
    18 22 extern "C"
    19 23 int main(int argc, char *argv[])
    20 24 {
    21 25 if (!app)
    22 26 {
    23 27 app=new filer_application;
    24 app->run(0);
    28 app->run(&pollword);
    25 29 delete app;
    26 30 app=0;
    27 31 }
  • trunk/filer/main.h

     
    7 7 #define FILER_MAIN
    8 8
    9 9 #include "filer_options.h"
    10 #include "pathname_table.h"
    10 11
    11 12 class filer_application;
    12 13
     
    17 18 * or 0 if the filer is not running. */
    18 19 extern filer_application* app;
    19 20
    21 /** The pollword used to notify the filer that there is a window to
    22 * be refreshed.
    23 * This variable must be located in global memory so that it is
    24 * accessible to the upcall handle (not in the application slot).
    25 */
    26 extern int pollword;
    27
    28 /** A table of pathnames with open filer windows.
    29 * This variable must be located in global memory so that it is
    30 * accessible to the upcall handle (not in the application slot).
    31 */
    32 extern pathname_table pathnames;
    33
    20 34 #endif
  • trunk/filer/pathname_find.s

     
    1 ; This file is part of the free Filer module for RISC OS.
    2 ; Copyright � 2007 Graham Shaw.
    3 ; Redistribution and modification are permitted under the terms of the
    4 ; GNU General Public License (version 2 or any later version).
    5
    6 GET _pathname_table.s
    7
    8 AREA |C$$Code|,CODE,READONLY,REL
    9
    10 ; Find pathname in table.
    11 ;
    12 ; On entry:
    13 ; R0=pathname table
    14 ; R1=hash
    15 ; On exit:
    16 ; R0=lower bound
    17 ; R1=upper bound
    18 ; R2-R3,R12 corrupted.
    19
    20 EXPORT |pathname_find|
    21 |pathname_find|
    22 STMFD R13!,{R4-R6,R14} ; Preserve registers
    23 MOV R12,R0 ; R12=pathname table
    24 MOV R0,R1 ; R1=hash
    25
    26 LDR R1,[R12,#table_index] ; R1=start of range
    27 LDR R2,[R12,#table_size] ; R2=size of table
    28 ADD R2,R1,R2,LSL#2 ; R2=end of range
    29
    30 TEQ R1,R2 ;
    31 BEQ |pathname_find_3| ; Jump if range empty
    32
    33 |pathname_find_0|
    34 ADD R3,R1,R2 ;
    35 MOV R3,R3,LSR#1 ;
    36 BIC R3,R3,#3 ; R3=middle of range (R1<=R3<R2)
    37 LDR R6,[R3] ; R6=value at middle of range
    38 CMP R0,R6 ;
    39 ADDHI R1,R3,#4 ; If target higher then move start of range
    40 MOVLO R2,R3 ; If target lower then move end of range
    41 TEQNE R1,R2 ;
    42 BNE |pathname_find_0| ; Repeat until found or range is empty
    43
    44 TEQ R1,R2 ;
    45 BEQ |pathname_find_3| ; Jump if range empty
    46
    47 MOV R4,R3 ; R4=top of range for lower bound
    48 ADD R5,R3,#4 ; R5=bottom of range for upper bound
    49
    50 TEQ R1,R4 ;
    51 BEQ |pathname_find_2| ; Jump if lower bound range empty
    52 |pathname_find_1|
    53 ADD R3,R1,R4 ;
    54 MOV R3,R3,LSR#1 ;
    55 BIC R3,R3,#3 ; R3=middle of range (R1<=R3<R4)
    56 LDR R6,[R3] ; R6=value at middle of range
    57 CMP R0,R6 ;
    58 MOVEQ R4,R3 ; If target matches then move end of range
    59 ADDNE R1,R3,#4 ; otherwise move start of range
    60 TEQ R1,R4 ;
    61 BNE |pathname_find_1| ; Repeat until range is empty
    62
    63 TEQ R5,R2 ;
    64 BEQ |pathname_find_3| ; Jump if upper bound range empty
    65 |pathname_find_2|
    66 ADD R3,R5,R2 ;
    67 MOV R3,R3,LSR#1 ;
    68 BIC R3,R3,#3 ; R3=middle of range (R5<=R3<R2)
    69 LDR R6,[R3] ; R6=value at middle of range
    70 CMP R0,R6 ;
    71 ADDEQ R5,R3,#4 ; If target matches then move start of range
    72 MOVNE R2,R3 ; otherwise move end of range
    73 TEQ R5,R2 ;
    74 BNE |pathname_find_2| ; Repeat until range is empty
    75
    76 |pathname_find_3|
    77 LDR R0,[R12,#table_index] ; R0=start of index
    78 SUB R1,R1,R0 ; R1=offset for lower bound
    79 SUB R2,R2,R0 ; R2=offset for upper bound
    80 MOV R0,R1,LSR#2 ; R0=lower bound
    81 MOV R1,R2,LSR#2 ; R1=upper bound
    82 LDMFD R13!,{R4-R6,PC} ; Return
    83
    84 END
  • trunk/filer/pathname_table.cc

     
    1 // This file is part of the free Filer module for RISC OS.
    2 // Copyright � 2007 Graham Shaw.
    3 // Redistribution and modification are permitted under the terms of the
    4 // GNU General Public License (version 2 or any later version).
    5
    6 #include <cstring>
    7 #include <cstdio>
    8
    9 #include "oslib/os.h"
    10 #include "oslib/osfscontrol.h"
    11
    12 #include "pathname_hash.h"
    13 #include "pathname_table.h"
    14 #include "filer_window.h"
    15
    16 // Rules for ensuring thread safety:
    17 // - the UpCall handler may search the index at any time (therefore _size
    18 // and the content of _index must be valid at all times).
    19 // - the UpCall handler may assume that the link referred to by _tail is
    20 // always null. It may change that link from null to non-null at any
    21 // time, provided that it first moves _tail to a different null link.
    22
    23 /** Upcall handler entry point.
    24 * The interface is as described in the PRM.
    25 */
    26 extern "C" void upcall_entry();
    27
    28 pathname_table::pathname_table(int* pollword):
    29 _size(0),
    30 _capacity(0),
    31 _index_data(0),
    32 _index_nodes(0),
    33 _tail(&_head),
    34 _pollword(pollword)
    35 {
    36 // Initialise refresh queue.
    37 _head.next=0;
    38
    39 // Initialise free list.
    40 _free.next=0;
    41
    42 // Activate upcall handler.
    43 xos_claim(UpCallV,(void*)upcall_entry,(byte*)this);
    44 }
    45
    46 pathname_table::~pathname_table()
    47 {
    48 // Deactivate upcall handler.
    49 xos_release(UpCallV,(void*)upcall_entry,(byte*)this);
    50
    51 // Deallocate nodes in index.
    52 for (unsigned int i=0;i!=_size;++i)
    53 {
    54 delete _index_nodes[i];
    55 }
    56
    57 // Deallocate nodes in free list.
    58 while (_free.next)
    59 {
    60 node* n=_free.next;
    61 _free.next=n->next;
    62 delete n;
    63 }
    64
    65 // Deallocate index.
    66 delete[] _index_data;
    67 delete[] _index_nodes;
    68 }
    69
    70 void pathname_table::reserve(size_type capacity)
    71 {
    72 // Each allocation is processed separately in order to avoid
    73 // a memory leak of one of them fails.
    74 if (_capacity<capacity)
    75 {
    76 // Reallocate index data (without allowing the existing index
    77 // to become invalid until it is no longer needed).
    78 int* new_index_data=new int[capacity];
    79 for (unsigned int i=0;i!=_size;++i)
    80 {
    81 new_index_data[i]=_index_data[i];
    82 }
    83 volatile int* old_index_data=_index_data;
    84 _index_data=new_index_data;
    85 delete[] old_index_data;
    86
    87 // Reallocate index node pointers (again, without allowing the
    88 // existing node pointers to become invalid until they are no
    89 // longer needed).
    90 volatile node** new_index_nodes=new volatile node*[capacity];
    91 for (unsigned int i=0;i!=_size;++i)
    92 {
    93 new_index_nodes[i]=_index_nodes[i];
    94 }
    95 volatile node** old_index_nodes=_index_nodes;
    96 _index_nodes=new_index_nodes;
    97 delete[] old_index_nodes;
    98
    99 // Create new nodes.
    100 while (_capacity<capacity)
    101 {
    102 node* n=new node;
    103 n->next=_free.next;
    104 _free.next=n;
    105 ++_capacity;
    106 }
    107 }
    108 }
    109
    110 pathname_table::node* pathname_table::insert(filer_window* w)
    111 {
    112 // Ensure there is sufficient capacity for one more node.
    113 reserve(_size+1);
    114
    115 // Parse pathname into filing system, special field and tail.
    116 char* pathtail=0;
    117 char* fs_special=0;
    118 fileswitch_fs_no fs_number=osfscontrol_set_temporary_fs(w->pathname(),
    119 &pathtail,&fs_special);
    120
    121 // Calculate hash of pathname.
    122 unsigned int hash=pathname_hash(pathtail,strlen(pathtail),
    123 fs_number,fs_special);
    124
    125 // Find point at which to insert.
    126 unsigned int f=pathname_find(this,hash);
    127
    128 // Select node from free list.
    129 node* n=_free.next;
    130 _free.next=n->next;
    131
    132 // Initialise node.
    133 n->next=0;
    134 n->refresh=0;
    135 n->window=w;
    136 n->index=f;
    137
    138 // Increment _size, after first ensuring that this will not cause
    139 // the index to become unordered.
    140 _index_data[_size]=0xffffffff;
    141 _index_nodes[_size]=0;
    142 ++_size;
    143
    144 // Make space for new index entry.
    145 for (unsigned int i=_size-1;i!=f;--i)
    146 {
    147 _index_data[i]=_index_data[i-1];
    148 _index_nodes[i]=_index_nodes[i-1];
    149 _index_nodes[i]->index=i;
    150 _index_nodes[i-1]=0;
    151 }
    152
    153 // Create new index entry.
    154 _index_data[f]=hash;
    155 _index_nodes[f]=n;
    156
    157 // Return pointer to node.
    158 return n;
    159 }
    160
    161 void pathname_table::erase(node* n)
    162 {
    163 // Get location of node in index.
    164 unsigned int f=n->index;
    165
    166 // Delete from index.
    167 // Each entry is modified as follows:
    168 // - first the link to the current node is broken
    169 // - next the hash is replaced with the new value
    170 // - finally the link to the new node is established
    171 // An index entry may therefore point to no node, or to the correct
    172 // node for the hash, but never to an incorrect node.
    173 _index_nodes[f]=0;
    174 for (unsigned int i=f+1;i!=_size;++i)
    175 {
    176 _index_data[i-1]=_index_data[i];
    177 _index_nodes[i-1]=_index_nodes[i];
    178 _index_nodes[i-1]->index=i-1;
    179 _index_nodes[i]=0;
    180 }
    181
    182 // Remove last entry from index.
    183 // The last entry is now an inactive duplicate of the penultimate
    184 // entry, and can be removed by decrementing the size.
    185 --_size;
    186
    187 // Return node to free list.
    188 n->next=_free.next;
    189 _free.next=n;
    190 }
    191
    192 void pathname_table::refresh()
    193 {
    194 if (_head.next)
    195 {
    196 // A chain has been started, so the UpCall handler will not now
    197 // alter _head until _tail is reset.
    198
    199 // Make a pointer to the first node in the chain.
    200 node* p=_head.next;
    201
    202 // Reset _head and _tail. The UpCall handler will not now make
    203 // any changes to the chain about to be processed.
    204 _head.next=0;
    205 _tail=&_head;
    206
    207 while (p)
    208 {
    209 // Keep a pointer to the current node, because the chain
    210 // pointer is about to move.
    211 node* n=p;
    212
    213 // Move the chain pointer forward now, because the link is
    214 // about to be cleared.
    215 p=n->next;
    216
    217 // Clear the forward link and the refresh pending flag
    218 // (in that order). This is done before the filer window
    219 // is refreshed so that if there is further disc activity
    220 // it is refreshed again.
    221 n->next=0;
    222 n->refresh=0;
    223
    224 // Refresh the filer window to which the node refers.
    225 n->window->refresh();
    226 }
    227 }
    228 }
  • trunk/filer/pathname_table.h

     
    1 // This file is part of the free Filer module for RISC OS.
    2 // Copyright � 2007 Graham Shaw.
    3 // Redistribution and modification are permitted under the terms of the
    4 // GNU General Public License (version 2 or any later version).
    5
    6 #ifndef FILER_PATHNAME_TABLE
    7 #define FILER_PATHNAME_TABLE
    8
    9 class filer_window;
    10
    11 /** A table for mapping pathnames to filer windows.
    12 * For speed, pathnames are hashed before they are indexed.
    13 * @note At present there is no mechanism for preventing hash collisions:
    14 * all matching filer windows are refreshed. This is considered acceptable.
    15 * @warning The layout of this class must match the offsets given
    16 * in the file "_pathname_table.s".
    17 */
    18 class pathname_table
    19 {
    20 public:
    21 /** A type to represent a number of index entries. */
    22 typedef unsigned int size_type;
    23
    24 /** A class to represent an entry in the table.
    25 * @warning The layout of this structure must match the offsets given
    26 * in the file "_pathname_table.s".
    27 */
    28 struct node
    29 {
    30 /** The next node in the refresh queue.
    31 * If this is the last node in the queue, or if this is not a
    32 * member of a queue, then the value of this field is undefined
    33 */
    34 node* next;
    35
    36 /** The refresh pending flag.
    37 * True if a refresh is pending for this node (and therefore,
    38 * it has been added to the refresh queue), otherwise false.
    39 */
    40 int refresh;
    41
    42 /** The filer window associated with this node. */
    43 filer_window* window;
    44
    45 /** The index entry occupied by this node.
    46 * This may change when other nodes are added or removed from
    47 * the index.
    48 */
    49 int index;
    50 };
    51 private:
    52 /** The number of nodes in the pathname table. */
    53 volatile size_type _size;
    54
    55 /** The capacity of the index. */
    56 size_type _capacity;
    57
    58 /** The index (pathname hash array).
    59 * This is a ordered array of pathname hashes. It must remain ordered
    60 * (for all indices less than _size) at all times.
    61 */
    62 volatile int* _index_data;
    63
    64 /** The index (node table). */
    65 volatile node** _index_nodes;
    66
    67 /** The tail of the refresh queue. */
    68 volatile node* _tail;
    69
    70 /** The pollword to be set if there are windows in need of a refresh. */
    71 int* _pollword;
    72
    73 /** A buffer for use by the upcall handler.
    74 * When the upcall handler is notified on an operation on a filehandle
    75 * it converts that filehandle into a pathname. For this is needs a
    76 * buffer to hold the pathname. Allocating from the RMA from within
    77 * the handler would be highly undesirable, therefore a suitable buffer
    78 * is permanently allocated.
    79 */
    80 char _pathname_buffer[256];
    81
    82 /** The head of the refresh queue.
    83 * Although this member is not referenced directly by the upcall
    84 * handler, it can be altered by the handler indirectly through _tail
    85 * (which may point to _head). For this reason it is marked as
    86 * volatile.
    87 */
    88 volatile node _head;
    89
    90 /** The head of the free list. */
    91 node _free;
    92 public:
    93 /** Construct pathname table.
    94 * @param pollword the pollword to be set if there are windows
    95 * in need of a refresh
    96 */
    97 pathname_table(int* pollword);
    98
    99 /** Destroy pathname table. */
    100 ~pathname_table();
    101
    102 /** Reserve capacity for index to reach given size.
    103 * @param capacity the required capacity of the index
    104 */
    105 void reserve(size_type capacity);
    106
    107 /** Insert filer window into table.
    108 * No action is taken if the filer window is already present.
    109 * @param w the filer window to be inserted
    110 */
    111 node* insert(filer_window* w);
    112
    113 /** Remove filer window from table.
    114 * No action is taken if the filer window is not found.
    115 * @param w the filer window to be removed
    116 */
    117 void erase(node* n);
    118
    119 /** Find filer window given pathname.
    120 * @param pathname the pathname for which to search
    121 * @return the corresponding filer window, or 0 if not found
    122 */
    123 filer_window* find(const char* pathname);
    124
    125 /** Refresh all filer windows for which a refresh is necessary. */
    126 void refresh();
    127 };
    128
    129 /** Find pathname in table.
    130 * @param table the pathname table
    131 * @param hash the hash of the pathname to be found
    132 * @param the index into the table of the first match, or table->_size
    133 * if not found
    134 */
    135 extern "C"
    136 unsigned int pathname_find(pathname_table* table,unsigned int hash);
    137
    138 #endif
  • trunk/filer/upcall_entry.s

     
    1 ; This file is part of the free Filer module for RISC OS.
    2 ; Copyright � 2007 Graham Shaw.
    3 ; Redistribution and modification are permitted under the terms of the
    4 ; GNU General Public License (version 2 or any later version).
    5
    6 GET _pathname_table.s
    7
    8 AREA |C$$Code|,CODE,READONLY,REL
    9
    10 IMPORT |upcall_refresh|
    11
    12 X EQU &20000
    13 OS_Args EQU &09
    14
    15 ; Upcall entry point.
    16 ;
    17 ; On entry:
    18 ; R0=upcall code (3=filesystem modification)
    19 ; R1-R7 depend on reason code
    20 ; R8=filing system information word
    21 ; R9=reason code
    22 ; R12=pathname table
    23 ; On exit:
    24 ; All registers must be preserved
    25 ;
    26 ; Note that there does not appear to be any reason to respond to
    27 ; reason code 258 (opening for update).
    28
    29 EXPORT |upcall_entry|
    30 |upcall_entry|
    31 TEQ R0,#3 ; If upcall code!=3
    32 MOVNE PC,R14 ; then return immediately
    33
    34 CMP R9,#9 ;
    35 BLO |upcall_pathname_0| ; Reason codes 0-8: R1=pathname
    36 SUB R9,R9,#&100 ;
    37 TEQ R9,#1 ;
    38 BEQ |upcall_pathname_100| ; Reason code &101: R1=pathname
    39 TEQ R9,#3 ;
    40 BEQ |upcall_filehandle_100| ; Reason code &103: R1=filehandle
    41 SUB R9,R9,#&100 ;
    42 TEQ R9,#0 ;
    43 BEQ |upcall_filehandle_200| ; Reason code &200: R1=filehandle
    44 TEQ R9,#8 ;
    45 BEQ |upcall_pathnames_200| ; Reason code &208: R1,R2=pathnames
    46 TEQ R9,#9 ;
    47 BEQ |upcall_pathname_200| ; Reason code &209: R1=pathname
    48 ADD R9,R9,#&200 ;
    49 MOV PC,R14 ; Return if reason not recognised
    50
    51 |upcall_pathname_200|
    52 ADD R9,R9,#&100 ; Restore R9 to original-&100
    53 |upcall_pathname_100|
    54 ADD R9,R9,#&100 ; Restore R9 to original value
    55 |upcall_pathname_0|
    56 STMFD R13!,{R0-R3,R14} ; Preserve registers
    57 MOV R0,R1 ; R0=pathname (no FS prefix)
    58 AND R1,R8,#&FF ; R1=filing system number
    59 MOV R2,R6 ; R2=fs special field
    60 BL |upcall_refresh| ; Process pathname
    61 LDMFD R13!,{R0-R3,PC} ; Restore registers and return
    62
    63 |upcall_pathnames_200|
    64 ADD R9,R9,#&200 ; Restore R9 to original value
    65 STMFD R13!,{R0-R3,R14} ; Preserve registers
    66 MOV R0,R1 ; R0=first pathname
    67 AND R1,R8,#&FF ; R1=filing system number
    68 MOV R2,R6 ; R2=first special field
    69 BL |upcall_refresh| ; Process first pathname
    70 LDR R0,[R13,#8] ; R0=second pathname
    71 AND R1,R8,#&FF ; R1=filing system number
    72 MOV R2,R7 ; R2=second special field
    73 BL |upcall_refresh| ; Process second pathname
    74 LDMFD R13!,{R0-R3,PC} ; Restore registers and return
    75
    76 |upcall_filehandle_200|
    77 ADD R9,R9,#&100 ; Restore R9 to original-&100
    78 |upcall_filehandle_100|
    79 ADD R9,R9,#&100 ; Restore R9 to original value
    80 STMFD R13!,{R0-R3,R5,R14} ; Preserve registers
    81 MOV R0,#7 ; R0=reason code 7 (to OS_Args)
    82 ADD R2,R12,#table_buffer ; R2=buffer for pathname
    83 MOV R5,#&100 ; R3=length of pathname buffer
    84 SWI X+OS_Args ; Get pathname for given file handle
    85 LDMVSFD R13!,{R0-R3,R5,PC} ; Return if error
    86
    87 MOV R0,R2 ; R0=pathname
    88 MOV R2,#0 ; R2=special field (default none)
    89
    90 |upcall_entry_0|
    91 LDRB R14,[R0],#1 ; R14=char from pathname
    92 TEQ R14,#'#' ;
    93 TEQEQ R2,#0 ;
    94 MOVEQ R2,R0 ; First hash is start of special field
    95 TEQ R14,#':' ;
    96 TEQNE R14,#0 ;
    97 BNE |upcall_entry_0| ; Repeat until colon or end
    98
    99 TEQ R14,#':' ; If colon found then replace with
    100 MOVEQ R14,#0 ; null (to terminate special field)
    101 STREQB R14,[R0],#1 ; and step forward
    102
    103 ; (A colon should never not be found, so there is no need to take
    104 ; any particular action except to ensure that the code is reasonably
    105 ; well-behaved.)
    106
    107 AND R1,R8,#&FF ; R1=filing system number
    108 BL |upcall_refresh| ; Process pathname
    109 LDMFD R13!,{R0-R3,R5,PC} ; Restore registers and return
    110
    111 END
  • trunk/filer/upcall_refresh.s

     
    1 ; This file is part of the free Filer module for RISC OS.
    2 ; Copyright � 2007 Graham Shaw.
    3 ; Redistribution and modification are permitted under the terms of the
    4 ; GNU General Public License (version 2 or any later version).
    5
    6 GET _pathname_table.s
    7
    8 AREA |C$$Code|,CODE,READONLY,REL
    9
    10 IMPORT |pathname_hash|
    11 IMPORT |pathname_find|
    12
    13 ; Find filer window associated with given pathname and filing system
    14 ; number, add to list of windows awaiting update.
    15 ;
    16 ; The given pathname is that of an object within the directory,
    17 ; therefore its leafname is removed before searching.
    18 ;
    19 ; On entry:
    20 ; R0=pathname (null terminated)
    21 ; R1=filing system number
    22 ; R2=filing system special field (null terminated) (or 0 if none)
    23 ; R12=pathname table
    24 ; On exit:
    25 ; R0-R3 corrupted (but R12 preserved)
    26
    27 EXPORT |upcall_refresh|
    28 |upcall_refresh|
    29 STMFD R13!,{R4,R12,R14} ; Preserve registers
    30
    31 MOV R4,R12 ; R4=pathname table
    32 MOV R3,R2 ; R3=fs special field (or 0)
    33 MOV R2,R1 ; R2=fs number
    34
    35 ; Remove final component of pathname.
    36 MOV R12,R0 ; R12=pointer into pathname
    37 MOV R1,#0 ; R1=pointer to last path separator
    38 ; (initially zero)
    39 |upcall_refresh_0|
    40 LDRB R14,[R12],#1 ; R14=char from pathname
    41 TEQ R14,#'.' ;
    42 SUBEQ R1,R12,#1 ; Update R1 if path separator found
    43 TEQ R14,#0 ;
    44 BNE |upcall_refresh_0| ; Repeat until end of pathname
    45
    46 TEQ R1,#0 ;
    47 SUBNE R1,R1,R0 ; R1=length of directory pathname
    48 BL |pathname_hash| ; R0=hash
    49
    50 MOV R1,R0 ; R1=hash
    51 MOV R0,R4 ; R0=pathname table
    52 BL |pathname_find| ; R0=lower bound, R1=upper bound
    53
    54 TEQ R0,R1 ;
    55 BEQ |upcall_refresh_3| ; Skip loop if range empty
    56 LDR R12,[R4,#table_nodes] ; R12=nodes array
    57 |upcall_refresh_1|
    58 LDR R2,[R12,R0,LSL#2] ; R2=pointer to node
    59 LDR R3,[R2,#node_refresh] ; R3=1 if refresh pending, otherwise 0
    60 TEQ R3,#0 ;
    61 BNE |upcall_refresh_2| ; Jump if refresh already pending
    62
    63 LDR R3,[R4,#table_tail] ; R3=pointer to tail node
    64 STR R2,[R4,#table_tail] ; Make node at R2 the tail node
    65 STR R2,[R3,#node_next] ; Link node at R2 into the chain
    66 MOV R3,#1 ;
    67 STR R3,[R2,#node_refresh] ; Mark node at R2 as refresh pending
    68 LDR R2,[R4,#table_pollword] ;
    69 STR R3,[R2] ; Set pollword
    70
    71 |upcall_refresh_2|
    72 ADD R0,R0,#1 ; Increment pointer into index
    73 TEQ R0,R1 ;
    74 BNE |upcall_refresh_1| ; Repeat until upper bound reached
    75
    76 |upcall_refresh_3|
    77 LDMFD R13!,{R4,R12,PC} ; Restore registers and return
    78
    79 END